ofproto: Add initialization function.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 1289025..6f63f83 100644 (file)
@@ -277,7 +277,7 @@ struct action_xlate_ctx {
     uint32_t orig_skb_priority; /* Priority when packet arrived. */
     uint8_t table_id;           /* OpenFlow table ID where flow was found. */
     uint32_t sflow_n_outputs;   /* Number of output ports. */
-    uint16_t sflow_odp_port;    /* Output port for composing sFlow action. */
+    uint32_t sflow_odp_port;    /* Output port for composing sFlow action. */
     uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */
     bool exit;                  /* No further actions should be processed. */
     struct flow orig_flow;      /* Copy of original flow. */
@@ -693,6 +693,11 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 \f
 /* Factory functions. */
 
+static void
+init(const struct shash *iface_hints OVS_UNUSED)
+{
+}
+
 static void
 enumerate_types(struct sset *types)
 {
@@ -1158,7 +1163,7 @@ get_features(struct ofproto *ofproto_ OVS_UNUSED,
 }
 
 static void
-get_tables(struct ofproto *ofproto_, struct ofp10_table_stats *ots)
+get_tables(struct ofproto *ofproto_, struct ofp12_table_stats *ots)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct dpif_dp_stats s;
@@ -1166,9 +1171,8 @@ get_tables(struct ofproto *ofproto_, struct ofp10_table_stats *ots)
     strcpy(ots->name, "classifier");
 
     dpif_get_dp_stats(ofproto->dpif, &s);
-    put_32aligned_be64(&ots->lookup_count, htonll(s.n_hit + s.n_missed));
-    put_32aligned_be64(&ots->matched_count,
-                       htonll(s.n_hit + ofproto->n_matches));
+    ots->lookup_count = htonll(s.n_hit + s.n_missed);
+    ots->matched_count = htonll(s.n_hit + ofproto->n_matches);
 }
 
 static struct ofport *
@@ -2532,7 +2536,7 @@ static int
 port_add(struct ofproto *ofproto_, struct netdev *netdev, uint16_t *ofp_portp)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
-    uint16_t odp_port = UINT16_MAX;
+    uint32_t odp_port = *ofp_portp != OFPP_NONE ? *ofp_portp : UINT32_MAX;
     int error;
 
     error = dpif_port_add(ofproto->dpif, netdev, &odp_port);
@@ -3046,6 +3050,7 @@ ofproto_dpif_extract_flow_key(const struct ofproto_dpif *ofproto,
     enum odp_key_fitness fitness;
 
     fitness = odp_flow_key_to_flow(key, key_len, flow);
+    flow->in_port = odp_port_to_ofp_port(flow->in_port);
     if (fitness == ODP_FIT_ERROR) {
         return fitness;
     }
@@ -3107,18 +3112,19 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
     for (upcall = upcalls; upcall < &upcalls[n_upcalls]; upcall++) {
         struct flow_miss *miss = &misses[n_misses];
         struct flow_miss *existing_miss;
+        struct flow flow;
         uint32_t hash;
 
         /* Obtain metadata and check userspace/kernel agreement on flow match,
          * then set 'flow''s header pointers. */
         miss->key_fitness = ofproto_dpif_extract_flow_key(
             ofproto, upcall->key, upcall->key_len,
-            &miss->flow, &miss->initial_tci, upcall->packet);
+            &flow, &miss->initial_tci, upcall->packet);
         if (miss->key_fitness == ODP_FIT_ERROR) {
             continue;
         }
-        flow_extract(upcall->packet, miss->flow.skb_priority,
-                     miss->flow.tun_id, miss->flow.in_port, &miss->flow);
+        flow_extract(upcall->packet, flow.skb_priority,
+                     &flow.tunnel, flow.in_port, &miss->flow);
 
         /* Add other packets to a to-do list. */
         hash = flow_hash(&miss->flow, 0);
@@ -3677,7 +3683,7 @@ execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow,
     int error;
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-    odp_flow_key_from_flow(&key, flow);
+    odp_flow_key_from_flow(&key, flow, ofp_port_to_odp_port(flow->in_port));
 
     error = dpif_execute(ofproto->dpif, key.data, key.size,
                          odp_actions, actions_len, packet);
@@ -4326,6 +4332,7 @@ subfacet_find(struct ofproto_dpif *ofproto,
     struct flow flow;
 
     fitness = odp_flow_key_to_flow(key, key_len, &flow);
+    flow.in_port = odp_port_to_ofp_port(flow.in_port);
     if (fitness == ODP_FIT_ERROR) {
         return NULL;
     }
@@ -4374,8 +4381,10 @@ subfacet_get_key(struct subfacet *subfacet, struct odputil_keybuf *keybuf,
                  struct ofpbuf *key)
 {
     if (!subfacet->key) {
+        struct flow *flow = &subfacet->facet->flow;
+
         ofpbuf_use_stack(key, keybuf, sizeof *keybuf);
-        odp_flow_key_from_flow(key, &subfacet->facet->flow);
+        odp_flow_key_from_flow(key, flow, ofp_port_to_odp_port(flow->in_port));
     } else {
         ofpbuf_use_const(key, subfacet->key, subfacet->key_len);
     }
@@ -4760,11 +4769,11 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
     const struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
     struct ofpbuf key, odp_actions;
     struct odputil_keybuf keybuf;
-    uint16_t odp_port;
+    uint32_t odp_port;
     struct flow flow;
     int error;
 
-    flow_extract(packet, 0, 0, 0, &flow);
+    flow_extract(packet, 0, NULL, 0, &flow);
     odp_port = vsp_realdev_to_vlandev(ofproto, ofport->odp_port,
                                       flow.vlan_tci);
     if (odp_port != ofport->odp_port) {
@@ -4773,7 +4782,7 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
     }
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-    odp_flow_key_from_flow(&key, &flow);
+    odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(flow.in_port));
 
     ofpbuf_init(&odp_actions, 32);
     compose_sflow_action(ofproto, &odp_actions, &flow, odp_port);
@@ -4950,7 +4959,7 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
                         bool check_stp)
 {
     const struct ofport_dpif *ofport = get_ofp_port(ctx->ofproto, ofp_port);
-    uint16_t odp_port = ofp_port_to_odp_port(ofp_port);
+    uint32_t odp_port = ofp_port_to_odp_port(ofp_port);
     ovs_be16 flow_vlan_tci = ctx->flow.vlan_tci;
     uint8_t flow_nw_tos = ctx->flow.nw_tos;
     uint16_t out_port;
@@ -4958,8 +4967,11 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
     if (ofport) {
         struct priority_to_dscp *pdscp;
 
-        if (ofport->up.pp.config & OFPUTIL_PC_NO_FWD
-            || (check_stp && !stp_forward_in_state(ofport->stp_state))) {
+        if (ofport->up.pp.config & OFPUTIL_PC_NO_FWD) {
+            xlate_report(ctx, "OFPPC_NO_FWD set, skipping output");
+            return;
+        } else if (check_stp && !stp_forward_in_state(ofport->stp_state)) {
+            xlate_report(ctx, "STP not in forwarding state, skipping output");
             return;
         }
 
@@ -5233,6 +5245,8 @@ xlate_output_action(struct action_xlate_ctx *ctx,
     default:
         if (port != ctx->flow.in_port) {
             compose_output_action(ctx, port);
+        } else {
+            xlate_report(ctx, "skipping output to input port");
         }
         break;
     }
@@ -5455,6 +5469,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
     }
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
         struct ofpact_controller *controller;
+        const struct ofpact_metadata *metadata;
 
         if (ctx->exit) {
             break;
@@ -5494,6 +5509,11 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             ctx->flow.vlan_tci = htons(0);
             break;
 
+        case OFPACT_PUSH_VLAN:
+            /* TODO:XXX 802.1AD(QinQ) */
+            ctx->flow.vlan_tci = htons(VLAN_CFI);
+            break;
+
         case OFPACT_SET_ETH_SRC:
             memcpy(ctx->flow.dl_src, ofpact_get_SET_ETH_SRC(a)->mac,
                    ETH_ADDR_LEN);
@@ -5533,7 +5553,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             break;
 
         case OFPACT_SET_TUNNEL:
-            ctx->flow.tun_id = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
+            ctx->flow.tunnel.tun_id = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
             break;
 
         case OFPACT_SET_QUEUE:
@@ -5594,6 +5614,29 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             ctx->has_fin_timeout = true;
             xlate_fin_timeout(ctx, ofpact_get_FIN_TIMEOUT(a));
             break;
+
+        case OFPACT_CLEAR_ACTIONS:
+            /* TODO:XXX
+             * Nothing to do because writa-actions is not supported for now.
+             * When writa-actions is supported, clear-actions also must
+             * be supported at the same time.
+             */
+            break;
+
+        case OFPACT_WRITE_METADATA:
+            metadata = ofpact_get_WRITE_METADATA(a);
+            ctx->flow.metadata &= ~metadata->mask;
+            ctx->flow.metadata |= metadata->metadata & metadata->mask;
+            break;
+
+        case OFPACT_GOTO_TABLE: {
+            /* TODO:XXX remove recursion */
+            /* It is assumed that goto-table is last action */
+            struct ofpact_goto_table *ogt = ofpact_get_GOTO_TABLE(a);
+            assert(ctx->table_id < ogt->table_id);
+            xlate_table_action(ctx, ctx->flow.in_port, ogt->table_id, true);
+            break;
+        }
         }
     }
 
@@ -5618,7 +5661,7 @@ action_xlate_ctx_init(struct action_xlate_ctx *ctx,
     ctx->ofproto = ofproto;
     ctx->flow = *flow;
     ctx->base_flow = ctx->flow;
-    ctx->base_flow.tun_id = 0;
+    memset(&ctx->base_flow.tunnel, 0, sizeof ctx->base_flow.tunnel);
     ctx->base_flow.vlan_tci = initial_tci;
     ctx->rule = rule;
     ctx->packet = packet;
@@ -6443,7 +6486,7 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
     struct ofpbuf odp_actions;
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
-    odp_flow_key_from_flow(&key, flow);
+    odp_flow_key_from_flow(&key, flow, ofp_port_to_odp_port(flow->in_port));
 
     dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
 
@@ -6761,7 +6804,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
         const char *tun_id_s = argv[3];
         const char *in_port_s = argv[4];
         const char *packet_s = argv[5];
-        uint16_t in_port = ofp_port_to_odp_port(atoi(in_port_s));
+        uint32_t in_port = atoi(in_port_s);
         ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0));
         uint32_t priority = atoi(priority_s);
         const char *msg;
@@ -6777,7 +6820,8 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
         ds_put_cstr(&result, s);
         free(s);
 
-        flow_extract(packet, priority, tun_id, in_port, &flow);
+        flow_extract(packet, priority, NULL, in_port, &flow);
+        flow.tunnel.tun_id = tun_id;
         initial_tci = flow.vlan_tci;
     } else {
         unixctl_command_reply_error(conn, "Bad command syntax");
@@ -7162,6 +7206,7 @@ vsp_add(struct ofport_dpif *port, uint16_t realdev_ofp_port, int vid)
 }
 \f
 const struct ofproto_class ofproto_dpif_class = {
+    init,
     enumerate_types,
     enumerate_names,
     del,