[ovs-dev] [PATCH 1/2] ofproto: Resubmit packet and byte count statistics.
Ethan Jackson
ethan at nicira.com
Tue Oct 12 22:34:05 UTC 2010
This patch maintains packet and byte count statistics when
resubmits are involved. For a particular rule A, it builds a tree
rooted at A of all rules which resubmit into it. Thus when
statistics are queried for A, it can incorporate its "children"
statistics as well.
---
ofproto/ofproto.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 115 insertions(+), 17 deletions(-)
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index e25ce28..401a11a 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -80,12 +80,6 @@ struct ofport {
static void ofport_free(struct ofport *);
static void hton_ofp_phy_port(struct ofp_phy_port *);
-static int xlate_actions(const union ofp_action *in, size_t n_in,
- const struct flow *, struct ofproto *,
- const struct ofpbuf *packet,
- struct odp_actions *out, tag_type *tags,
- bool *may_set_up_flow, uint16_t *nf_output_iface);
-
struct rule {
struct cls_rule cr;
@@ -131,8 +125,27 @@ struct rule {
* be reassessed for every packet. */
int n_odp_actions;
union odp_action *odp_actions;
+
+ /* Resubmit Tree.
+ *
+ * Rules maintain a "resubmit tree" used to keep track of packet and byte
+ * count statistics. Suppose rule_a resubmits into rule_b. In this case,
+ * rule_b will maintain the rule_a rs_node in its rs_children list. In
+ * addition rule_a will store rule_b in its rs_parent. */
+ struct rule *rs_parent;
+ struct list rs_node;
+ struct list rs_children;
};
+static int xlate_actions(const union ofp_action *in, size_t n_in,
+ struct rule *, const struct flow *,
+ struct ofproto *, const struct ofpbuf *packet,
+ struct odp_actions *out, tag_type *tags,
+ bool *may_set_up_flow, uint16_t *nf_output_iface);
+
+static void query_stats(struct ofproto *, struct rule *,
+ uint64_t *packet_countp, uint64_t *byte_countp);
+
static inline bool
rule_is_hidden(const struct rule *rule)
{
@@ -170,6 +183,9 @@ static void rule_uninstall(struct ofproto *, struct rule *);
static void rule_post_uninstall(struct ofproto *, struct rule *);
static void send_flow_removed(struct ofproto *p, struct rule *rule,
long long int now, uint8_t reason);
+static void add_resubmit_rule(struct ofproto *,
+ struct rule *parent, struct rule *);
+static void del_resubmit_rule(struct ofproto *, struct rule *);
/* ofproto supports two kinds of OpenFlow connections:
*
@@ -1285,7 +1301,8 @@ ofproto_send_packet(struct ofproto *p, const struct flow *flow,
struct odp_actions odp_actions;
int error;
- error = xlate_actions(actions, n_actions, flow, p, packet, &odp_actions,
+ error = xlate_actions(actions, n_actions, NULL,
+ flow, p, packet, &odp_actions,
NULL, NULL, NULL);
if (error) {
return error;
@@ -1854,6 +1871,9 @@ rule_create(struct ofproto *ofproto, struct rule *super,
rule->n_actions = n_actions;
rule->actions = xmemdup(actions, n_actions * sizeof *actions);
}
+
+ list_init(&rule->rs_node);
+ list_init(&rule->rs_children);
netflow_flow_clear(&rule->nf_flow);
netflow_flow_update_time(ofproto->netflow, &rule->nf_flow, rule->created);
@@ -1885,6 +1905,8 @@ rule_free(struct rule *rule)
static void
rule_destroy(struct ofproto *ofproto, struct rule *rule)
{
+ del_resubmit_rule(ofproto, rule);
+
if (!rule->super) {
struct rule *subrule, *next;
LIST_FOR_EACH_SAFE (subrule, next, list, &rule->list) {
@@ -1896,6 +1918,61 @@ rule_destroy(struct ofproto *ofproto, struct rule *rule)
rule_free(rule);
}
+/* Deletes 'rule' from the resubmit tree it may or may not be in. This involves
+ * removing 'rule' from it's parent, updating it's parent's count statistics,
+ * and updating it's children */
+static void
+del_resubmit_rule(struct ofproto *ofproto, struct rule *rule)
+{
+
+ if (rule->rs_parent) {
+ uint64_t packet_count, byte_count;
+
+ query_stats(ofproto, rule, &packet_count, &byte_count);
+
+ assert(!list_is_empty(&rule->rs_node));
+ list_remove(&rule->rs_node);
+ list_init(&rule->rs_node);
+
+ rule->rs_parent->packet_count += packet_count;
+ rule->rs_parent->byte_count += byte_count;
+ rule->rs_parent = NULL;
+ }
+
+ if (!list_is_empty(&rule->rs_children)) {
+ struct rule *child, *child_next;
+ ofproto->need_revalidate = true;
+
+ LIST_FOR_EACH_SAFE(child, child_next, rs_node, &rule->rs_children) {
+ child->rs_parent = NULL;
+ list_remove(&child->rs_node);
+ list_init(&child->rs_node);
+ }
+ }
+}
+
+/* Add 'rule' to the resubmit tree of 'parent'. */
+static void
+add_resubmit_rule(struct ofproto *ofproto,
+ struct rule *parent, struct rule *rule)
+{
+ uint64_t packet_count, byte_count;
+
+ if (rule->rs_parent == parent) {
+ return;
+ }
+
+ assert(parent != rule);
+
+ del_resubmit_rule(ofproto, rule);
+ query_stats(ofproto, rule, &packet_count, &byte_count);
+ parent->packet_count -= packet_count;
+ parent->byte_count -= byte_count;
+
+ rule->rs_parent = parent;
+ list_push_back(&parent->rs_children, &rule->rs_node);
+}
+
static bool
rule_has_out_port(const struct rule *rule, uint16_t out_port)
{
@@ -1984,7 +2061,8 @@ rule_execute(struct ofproto *ofproto, struct rule *rule,
* scenario. */
if (rule->cr.wc.wildcards || !flow_equal(flow, &rule->cr.flow)) {
struct rule *super = rule->super ? rule->super : rule;
- if (xlate_actions(super->actions, super->n_actions, flow, ofproto,
+ if (xlate_actions(super->actions, super->n_actions,
+ rule, flow, ofproto,
packet, &a, NULL, 0, NULL)) {
ofpbuf_delete(packet);
return;
@@ -2075,6 +2153,8 @@ rule_create_subrule(struct ofproto *ofproto, struct rule *rule,
static void
rule_remove(struct ofproto *ofproto, struct rule *rule)
{
+ del_resubmit_rule(ofproto, rule);
+
if (rule->cr.wc.wildcards) {
COVERAGE_INC(ofproto_del_wc_flow);
ofproto->need_revalidate = true;
@@ -2090,7 +2170,7 @@ static bool
rule_make_actions(struct ofproto *p, struct rule *rule,
const struct ofpbuf *packet)
{
- const struct rule *super;
+ struct rule *super;
struct odp_actions a;
size_t actions_len;
@@ -2098,7 +2178,7 @@ rule_make_actions(struct ofproto *p, struct rule *rule,
super = rule->super ? rule->super : rule;
rule->tags = 0;
- xlate_actions(super->actions, super->n_actions, &rule->cr.flow, p,
+ xlate_actions(super->actions, super->n_actions, rule, &rule->cr.flow, p,
packet, &a, &rule->tags, &rule->may_install,
&rule->nf_flow.output_iface);
@@ -2439,6 +2519,7 @@ add_controller_action(struct odp_actions *actions, uint16_t max_len)
struct action_xlate_ctx {
/* Input. */
+ struct rule *rule; /* Rule to which these actions correspond. */
struct flow flow; /* Flow to which these actions correspond. */
int recurse; /* Recursion level, via xlate_table_action. */
struct ofproto *ofproto;
@@ -2518,13 +2599,19 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port)
ctx->flow.in_port = old_in_port;
if (rule) {
- if (rule->super) {
- rule = rule->super;
- }
+ struct rule *ctx_rule;
+ ctx_rule = ctx->rule;
+ ctx->rule = ctx->rule ? rule : NULL;
ctx->recurse++;
do_xlate_actions(rule->actions, rule->n_actions, ctx);
ctx->recurse--;
+ ctx->rule = ctx_rule;
+
+ if (ctx->rule) {
+ add_resubmit_rule(ctx->ofproto, rule, ctx->rule);
+ }
+
}
} else {
struct vlog_rate_limit recurse_rl = VLOG_RATE_LIMIT_INIT(1, 1);
@@ -2835,8 +2922,8 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
static int
xlate_actions(const union ofp_action *in, size_t n_in,
- const struct flow *flow, struct ofproto *ofproto,
- const struct ofpbuf *packet,
+ struct rule *rule, const struct flow *flow,
+ struct ofproto *ofproto, const struct ofpbuf *packet,
struct odp_actions *out, tag_type *tags, bool *may_set_up_flow,
uint16_t *nf_output_iface)
{
@@ -2844,6 +2931,7 @@ xlate_actions(const union ofp_action *in, size_t n_in,
struct action_xlate_ctx ctx;
COVERAGE_INC(ofproto_ofp2odp);
odp_actions_init(out);
+ ctx.rule = rule;
ctx.flow = *flow;
ctx.recurse = 0;
ctx.ofproto = ofproto;
@@ -2935,7 +3023,7 @@ handle_packet_out(struct ofproto *p, struct ofconn *ofconn,
flow_extract(&payload, 0, ofp_port_to_odp_port(ntohs(opo->in_port)), &flow);
error = xlate_actions((const union ofp_action *) opo->actions, n_actions,
- &flow, p, &payload, &actions, NULL, NULL, NULL);
+ NULL, &flow, p, &payload, &actions, NULL, NULL, NULL);
if (error) {
return error;
}
@@ -3182,7 +3270,7 @@ query_stats(struct ofproto *p, struct rule *rule,
uint64_t *packet_countp, uint64_t *byte_countp)
{
uint64_t packet_count, byte_count;
- struct rule *subrule;
+ struct rule *subrule, *rs_rule;
struct odp_flow *odp_flows;
size_t n_odp_flows;
@@ -3223,6 +3311,16 @@ query_stats(struct ofproto *p, struct rule *rule,
}
free(odp_flows);
+ LIST_FOR_EACH (rs_rule, rs_node, &rule->rs_children) {
+ uint64_t rs_packet_count, rs_byte_count;
+
+ assert(rs_rule->rs_parent == rule);
+
+ query_stats(p, rs_rule, &rs_packet_count, &rs_byte_count);
+ packet_count += rs_packet_count;
+ byte_count += rs_byte_count;
+ }
+
/* Return the stats to the caller. */
*packet_countp = packet_count;
*byte_countp = byte_count;
--
1.7.3.1
More information about the dev
mailing list