ofproto: Correctly compute length of flow stats in multipart flow stats.
[openvswitch] / ofproto / ofproto.c
index c7f211ae3f93328823ebc0a038068c1033363c75..7df8600e54b853c9c8859b691b7968440147bfe7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011 Nicira Networks.
  * Copyright (c) 2010 Jean Tourrilhes - HP-Labs.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,6 +35,7 @@
 #include "hmap.h"
 #include "in-band.h"
 #include "mac-learning.h"
+#include "multipath.h"
 #include "netdev.h"
 #include "netflow.h"
 #include "netlink.h"
@@ -1480,7 +1481,8 @@ ofproto_flush_flows(struct ofproto *ofproto)
 static void
 reinit_ports(struct ofproto *p)
 {
-    struct svec devnames;
+    struct shash_node *node;
+    struct shash devnames;
     struct ofport *ofport;
     struct odp_port *odp_ports;
     size_t n_odp_ports;
@@ -1488,21 +1490,20 @@ reinit_ports(struct ofproto *p)
 
     COVERAGE_INC(ofproto_reinit_ports);
 
-    svec_init(&devnames);
+    shash_init(&devnames);
     HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
-        svec_add (&devnames, ofport->opp.name);
+        shash_add_once (&devnames, ofport->opp.name, NULL);
     }
     dpif_port_list(p->dpif, &odp_ports, &n_odp_ports);
     for (i = 0; i < n_odp_ports; i++) {
-        svec_add (&devnames, odp_ports[i].devname);
+        shash_add_once (&devnames, odp_ports[i].devname, NULL);
     }
     free(odp_ports);
 
-    svec_sort_unique(&devnames);
-    for (i = 0; i < devnames.n; i++) {
-        update_port(p, devnames.names[i]);
+    SHASH_FOR_EACH (node, &devnames) {
+        update_port(p, node->name);
     }
-    svec_destroy(&devnames);
+    shash_destroy(&devnames);
 }
 
 static struct ofport *
@@ -2478,8 +2479,6 @@ facet_revalidate(struct ofproto *ofproto, struct facet *facet)
         facet_flush_stats(ofproto, facet);
     }
 
-    ofpbuf_delete(odp_actions);
-
     /* Update 'facet' now that we've taken care of all the old state. */
     facet->tags = ctx.tags;
     facet->nf_flow.output_iface = ctx.nf_output_iface;
@@ -2497,6 +2496,8 @@ facet_revalidate(struct ofproto *ofproto, struct facet *facet)
         facet->used = new_rule->created;
     }
 
+    ofpbuf_delete(odp_actions);
+
     return true;
 }
 \f
@@ -2514,7 +2515,7 @@ static void
 send_error_oh(const struct ofconn *ofconn, const struct ofp_header *oh,
               int error)
 {
-    struct ofpbuf *buf = make_ofp_error_msg(error, oh);
+    struct ofpbuf *buf = ofputil_encode_error_msg(error, oh);
     if (buf) {
         COVERAGE_INC(ofproto_error);
         queue_tx(buf, ofconn, ofconn->reply_counter);
@@ -2622,7 +2623,7 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc)
 
 /* Maximum depth of flow table recursion (due to NXAST_RESUBMIT actions) in a
  * flow translation. */
-#define MAX_RESUBMIT_RECURSION 8
+#define MAX_RESUBMIT_RECURSION 16
 
 static void do_xlate_actions(const union ofp_action *in, size_t n_in,
                              struct action_xlate_ctx *ctx);
@@ -2680,7 +2681,7 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port)
             ctx->recurse--;
         }
     } else {
-        struct vlog_rate_limit recurse_rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        static struct vlog_rate_limit recurse_rl = VLOG_RATE_LIMIT_INIT(1, 1);
 
         VLOG_ERR_RL(&recurse_rl, "NXAST_RESUBMIT recursed over %d times",
                     MAX_RESUBMIT_RECURSION);
@@ -2857,17 +2858,29 @@ xlate_set_dl_tci(struct action_xlate_ctx *ctx)
     }
 }
 
+struct xlate_reg_state {
+    ovs_be16 vlan_tci;
+    ovs_be64 tun_id;
+};
+
 static void
-xlate_reg_move_action(struct action_xlate_ctx *ctx,
-                      const struct nx_action_reg_move *narm)
+save_reg_state(const struct action_xlate_ctx *ctx,
+               struct xlate_reg_state *state)
 {
-    ovs_be16 old_tci = ctx->flow.vlan_tci;
-
-    nxm_execute_reg_move(narm, &ctx->flow);
+    state->vlan_tci = ctx->flow.vlan_tci;
+    state->tun_id = ctx->flow.tun_id;
+}
 
-    if (ctx->flow.vlan_tci != old_tci) {
+static void
+update_reg_state(struct action_xlate_ctx *ctx,
+                 const struct xlate_reg_state *state)
+{
+    if (ctx->flow.vlan_tci != state->vlan_tci) {
         xlate_set_dl_tci(ctx);
     }
+    if (ctx->flow.tun_id != state->tun_id) {
+        nl_msg_put_be64(ctx->odp_actions, ODPAT_SET_TUNNEL, ctx->flow.tun_id);
+    }
 }
 
 static void
@@ -2877,7 +2890,9 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,
     const struct nx_action_resubmit *nar;
     const struct nx_action_set_tunnel *nast;
     const struct nx_action_set_queue *nasq;
+    const struct nx_action_multipath *nam;
     enum nx_action_subtype subtype = ntohs(nah->subtype);
+    struct xlate_reg_state state;
     ovs_be64 tun_id;
 
     assert(nah->vendor == htonl(NX_VENDOR_ID));
@@ -2910,12 +2925,18 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,
         break;
 
     case NXAST_REG_MOVE:
-        xlate_reg_move_action(ctx, (const struct nx_action_reg_move *) nah);
+        save_reg_state(ctx, &state);
+        nxm_execute_reg_move((const struct nx_action_reg_move *) nah,
+                             &ctx->flow);
+        update_reg_state(ctx, &state);
         break;
 
     case NXAST_REG_LOAD:
+        save_reg_state(ctx, &state);
         nxm_execute_reg_load((const struct nx_action_reg_load *) nah,
                              &ctx->flow);
+        update_reg_state(ctx, &state);
+        break;
 
     case NXAST_NOTE:
         /* Nothing to do. */
@@ -2927,6 +2948,11 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,
         ctx->flow.tun_id = tun_id;
         break;
 
+    case NXAST_MULTIPATH:
+        nam = (const struct nx_action_multipath *) nah;
+        multipath_execute(nam, &ctx->flow);
+        break;
+
     /* If you add a new action here that modifies flow data, don't forget to
      * update the flow key in ctx->flow at the same time. */
 
@@ -3258,7 +3284,7 @@ make_nxstats_reply(ovs_be32 xid, ovs_be32 subtype, size_t body_len)
     nsm->type = htons(OFPST_VENDOR);
     nsm->flags = htons(0);
     nsm->vendor = htonl(NX_VENDOR_ID);
-    nsm->subtype = htonl(subtype);
+    nsm->subtype = subtype;
     return msg;
 }
 
@@ -3523,8 +3549,8 @@ put_nx_flow_stats(struct ofconn *ofconn, struct rule *rule,
 
     act_len = sizeof *rule->actions * rule->n_actions;
 
-    start_len = (*replyp)->size;
     append_nxstats_reply(sizeof *nfs + NXM_MAX_LEN + act_len, ofconn, replyp);
+    start_len = (*replyp)->size;
     reply = *replyp;
 
     nfs = ofpbuf_put_uninit(reply, sizeof *nfs);
@@ -4678,7 +4704,7 @@ compose_ofp_flow_removed(struct ofconn *ofconn, const struct rule *rule,
     struct ofp_flow_removed *ofr;
     struct ofpbuf *buf;
 
-    ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf);
+    ofr = make_openflow_xid(sizeof *ofr, OFPT_FLOW_REMOVED, htonl(0), &buf);
     ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofr->match,
                               rule->flow_cookie, &ofr->cookie);
     ofr->priority = htons(rule->cr.priority);
@@ -4698,10 +4724,10 @@ compose_nx_flow_removed(const struct rule *rule, uint8_t reason)
     struct ofpbuf *buf;
     int match_len;
 
-    nfr = make_nxmsg(sizeof *nfr, NXT_FLOW_REMOVED, &buf);
-
+    make_nxmsg_xid(sizeof *nfr, NXT_FLOW_REMOVED, htonl(0), &buf);
     match_len = nx_put_match(buf, &rule->cr);
 
+    nfr = buf->data;
     nfr->cookie = rule->flow_cookie;
     nfr->priority = htons(rule->cr.priority);
     nfr->reason = reason;
@@ -5000,7 +5026,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
     struct ds result;
     struct flow flow;
     uint16_t in_port;
-    ovs_be32 tun_id;
+    ovs_be64 tun_id;
     char *s;
 
     ofpbuf_init(&packet, strlen(args) / 2);
@@ -5022,7 +5048,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
         goto exit;
     }
 
-    tun_id = ntohl(strtoul(tun_id_s, NULL, 10));
+    tun_id = htonll(strtoull(tun_id_s, NULL, 10));
     in_port = ofp_port_to_odp_port(atoi(in_port_s));
 
     packet_s = ofpbuf_put_hex(&packet, packet_s, NULL);