tunnel: Hide 'struct tnl_port' internally.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 0f688d7..f8a1912 100644 (file)
@@ -571,7 +571,7 @@ type_run(const char *type)
                 char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
                 const char *dp_port;
 
-                if (!iter->tnl_port) {
+                if (!iter->is_tunnel) {
                     continue;
                 }
 
@@ -597,8 +597,8 @@ type_run(const char *type)
                 }
 
                 iter->odp_port = node ? u32_to_odp(node->data) : ODPP_NONE;
-                if (tnl_port_reconfigure(&iter->up, iter->odp_port,
-                                         &iter->tnl_port)) {
+                if (tnl_port_reconfigure(iter, iter->up.netdev,
+                                         iter->odp_port)) {
                     backer->need_revalidate = REV_RECONFIGURE;
                 }
             }
@@ -1045,8 +1045,6 @@ construct(struct ofproto *ofproto_)
     ofproto_dpif_unixctl_init();
 
     ofproto->has_mirrors = false;
-    ofproto->has_bundle_action = false;
-
     hmap_init(&ofproto->vlandev_map);
     hmap_init(&ofproto->realdev_vid_map);
 
@@ -1195,9 +1193,9 @@ destruct(struct ofproto *ofproto_)
     }
 
     netflow_destroy(ofproto->netflow);
-    dpif_sflow_destroy(ofproto->sflow);
+    dpif_sflow_unref(ofproto->sflow);
     hmap_destroy(&ofproto->bundles);
-    mac_learning_destroy(ofproto->ml);
+    mac_learning_unref(ofproto->ml);
 
     classifier_destroy(&ofproto->facets);
 
@@ -1459,7 +1457,7 @@ port_construct(struct ofport *port_)
     port->may_enable = true;
     port->stp_port = NULL;
     port->stp_state = STP_DISABLED;
-    port->tnl_port = NULL;
+    port->is_tunnel = false;
     port->peer = NULL;
     hmap_init(&port->priorities);
     port->realdev_ofp_port = 0;
@@ -1488,7 +1486,8 @@ port_construct(struct ofport *port_)
     port->odp_port = dpif_port.port_no;
 
     if (netdev_get_tunnel_config(netdev)) {
-        port->tnl_port = tnl_port_add(&port->up, port->odp_port);
+        tnl_port_add(port, port->up.netdev, port->odp_port);
+        port->is_tunnel = true;
     } else {
         /* Sanity-check that a mapping doesn't already exist.  This
          * shouldn't happen for non-tunnel ports. */
@@ -1500,7 +1499,7 @@ port_construct(struct ofport *port_)
         }
 
         hmap_insert(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node,
-                    hash_int(odp_to_u32(port->odp_port), 0));
+                    hash_odp_port(port->odp_port));
     }
     dpif_port_destroy(&dpif_port);
 
@@ -1520,6 +1519,8 @@ port_destruct(struct ofport *port_)
     char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
     const char *dp_port_name;
 
+    ofproto->backer->need_revalidate = REV_RECONFIGURE;
+
     dp_port_name = netdev_vport_get_dpif_port(port->up.netdev, namebuf,
                                               sizeof namebuf);
     if (dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
@@ -1527,10 +1528,9 @@ port_destruct(struct ofport *port_)
          * happens when the ofproto is being destroyed, since the caller
          * assumes that removal of attached ports will happen as part of
          * destruction. */
-        if (!port->tnl_port) {
+        if (!port->is_tunnel) {
             dpif_port_del(ofproto->backer->dpif, port->odp_port);
         }
-        ofproto->backer->need_revalidate = REV_RECONFIGURE;
     }
 
     if (port->peer) {
@@ -1538,14 +1538,13 @@ port_destruct(struct ofport *port_)
         port->peer = NULL;
     }
 
-    if (port->odp_port != ODPP_NONE && !port->tnl_port) {
+    if (port->odp_port != ODPP_NONE && !port->is_tunnel) {
         hmap_remove(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node);
     }
 
-    tnl_port_del(port->tnl_port);
+    tnl_port_del(port);
     sset_find_and_delete(&ofproto->ports, devname);
     sset_find_and_delete(&ofproto->ghost_ports, devname);
-    ofproto->backer->need_revalidate = REV_RECONFIGURE;
     bundle_remove(port_);
     set_cfm(port_, NULL);
     set_bfd(port_, NULL);
@@ -1570,9 +1569,10 @@ port_modified(struct ofport *port_)
         cfm_set_netdev(port->cfm, port->up.netdev);
     }
 
-    if (port->tnl_port && tnl_port_reconfigure(&port->up, port->odp_port,
-                                               &port->tnl_port)) {
-        ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate = true;
+    if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
+                                                port->odp_port)) {
+        ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
+            REV_RECONFIGURE;
     }
 
     ofport_update_peer(port);
@@ -1616,7 +1616,7 @@ set_sflow(struct ofproto *ofproto_,
         dpif_sflow_set_options(ds, sflow_options);
     } else {
         if (ds) {
-            dpif_sflow_destroy(ds);
+            dpif_sflow_unref(ds);
             ofproto->backer->need_revalidate = REV_RECONFIGURE;
             ofproto->sflow = NULL;
         }
@@ -1643,7 +1643,7 @@ set_ipfix(
             n_flow_exporters_options);
     } else {
         if (di) {
-            dpif_ipfix_destroy(di);
+            dpif_ipfix_unref(di);
             ofproto->ipfix = NULL;
         }
     }
@@ -1673,7 +1673,7 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 
         error = EINVAL;
     }
-    cfm_destroy(ofport->cfm);
+    cfm_unref(ofport->cfm);
     ofport->cfm = NULL;
     return error;
 }
@@ -2244,8 +2244,8 @@ bundle_destroy(struct ofbundle *bundle)
     hmap_remove(&ofproto->bundles, &bundle->hmap_node);
     free(bundle->name);
     free(bundle->trunks);
-    lacp_destroy(bundle->lacp);
-    bond_destroy(bundle->bond);
+    lacp_unref(bundle->lacp);
+    bond_unref(bundle->bond);
     free(bundle);
 }
 
@@ -2308,7 +2308,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
         }
         lacp_configure(bundle->lacp, s->lacp);
     } else {
-        lacp_destroy(bundle->lacp);
+        lacp_unref(bundle->lacp);
         bundle->lacp = NULL;
     }
 
@@ -2419,7 +2419,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
             bond_slave_register(bundle->bond, port, port->up.netdev);
         }
     } else {
-        bond_destroy(bundle->bond);
+        bond_unref(bundle->bond);
         bundle->bond = NULL;
     }
 
@@ -2443,7 +2443,7 @@ bundle_remove(struct ofport *port_)
         if (list_is_empty(&bundle->ports)) {
             bundle_destroy(bundle);
         } else if (list_is_short(&bundle->ports)) {
-            bond_destroy(bundle->bond);
+            bond_unref(bundle->bond);
             bundle->bond = NULL;
         }
     }
@@ -2859,7 +2859,7 @@ ofport_update_peer(struct ofport_dpif *ofport)
     }
 
     backer = ofproto_dpif_cast(ofport->up.ofproto)->backer;
-    backer->need_revalidate = true;
+    backer->need_revalidate = REV_RECONFIGURE;
 
     if (ofport->peer) {
         ofport->peer->peer = NULL;
@@ -2955,10 +2955,7 @@ port_run(struct ofport_dpif *ofport)
 
     if (ofport->may_enable != enable) {
         struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
-
-        if (ofproto->has_bundle_action) {
-            ofproto->backer->need_revalidate = REV_PORT_TOGGLED;
-        }
+        ofproto->backer->need_revalidate = REV_PORT_TOGGLED;
     }
 
     ofport->may_enable = enable;
@@ -3063,7 +3060,7 @@ port_del(struct ofproto *ofproto_, ofp_port_t ofp_port)
     sset_find_and_delete(&ofproto->ghost_ports,
                          netdev_get_name(ofport->up.netdev));
     ofproto->backer->need_revalidate = REV_RECONFIGURE;
-    if (!ofport->tnl_port) {
+    if (!ofport->is_tunnel) {
         error = dpif_port_del(ofproto->backer->dpif, ofport->odp_port);
         if (!error) {
             /* The caller is going to close ofport->up.netdev.  If this is a
@@ -3247,6 +3244,9 @@ struct flow_miss_op {
     struct xlate_out xout;
     bool xout_garbage;           /* 'xout' needs to be uninitialized? */
 
+    struct ofpbuf mask;          /* Flow mask for "put" ops. */
+    struct odputil_keybuf maskbuf;
+
     /* If this is a "put" op, then a pointer to the subfacet that should
      * be marked as uninstalled if the operation fails. */
     struct subfacet *subfacet;
@@ -3318,6 +3318,7 @@ init_flow_miss_execute_op(struct flow_miss *miss, struct ofpbuf *packet,
     op->dpif_op.u.execute.key = miss->key;
     op->dpif_op.u.execute.key_len = miss->key_len;
     op->dpif_op.u.execute.packet = packet;
+    ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
 }
 
 /* Helper for handle_flow_miss_without_facet() and
@@ -3356,6 +3357,15 @@ flow_miss_should_make_facet(struct flow_miss *miss, struct flow_wildcards *wc)
     struct dpif_backer *backer = miss->ofproto->backer;
     uint32_t hash;
 
+    switch (flow_miss_model) {
+    case OFPROTO_HANDLE_MISS_AUTO:
+        break;
+    case OFPROTO_HANDLE_MISS_WITH_FACETS:
+        return true;
+    case OFPROTO_HANDLE_MISS_WITHOUT_FACETS:
+        return false;
+    }
+
     if (!backer->governor) {
         size_t n_subfacets;
 
@@ -3465,14 +3475,19 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet,
 
         subfacet->path = want_path;
 
+        ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
+        odp_flow_key_from_mask(&op->mask, &facet->xout.wc.masks,
+                               &miss->flow, UINT32_MAX);
+
         op->xout_garbage = false;
         op->dpif_op.type = DPIF_OP_FLOW_PUT;
         op->subfacet = subfacet;
         put->flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
         put->key = miss->key;
         put->key_len = miss->key_len;
-        put->mask = NULL;
-        put->mask_len = 0;
+        put->mask = op->mask.data;
+        put->mask_len = op->mask.size;
+
         if (want_path == SF_FAST_PATH) {
             put->actions = facet->xout.odp_actions.data;
             put->actions_len = facet->xout.odp_actions.size;
@@ -3627,7 +3642,7 @@ ofproto_receive(const struct dpif_backer *backer, struct ofpbuf *packet,
     }
 
     port = (tnl_port_should_receive(flow)
-            ? ofport_dpif_cast(tnl_port_receive(flow))
+            ? tnl_port_receive(flow)
             : odp_port_to_ofport(backer, flow->in_port.odp_port));
     flow->in_port.ofp_port = port ? port->up.ofp_port : OFPP_NONE;
     if (!port) {
@@ -4136,12 +4151,12 @@ update_stats(struct dpif_backer *backer)
 {
     const struct dpif_flow_stats *stats;
     struct dpif_flow_dump dump;
-    const struct nlattr *key;
-    size_t key_len;
+    const struct nlattr *key, *mask;
+    size_t key_len, mask_len;
 
     dpif_flow_dump_start(&dump, backer->dpif);
     while (dpif_flow_dump_next(&dump, &key, &key_len,
-                               NULL, NULL, NULL, NULL, &stats)) {
+                               &mask, &mask_len, NULL, NULL, &stats)) {
         struct subfacet *subfacet;
         uint32_t key_hash;
 
@@ -4825,7 +4840,7 @@ facet_push_stats(struct facet *facet, bool may_learn)
         facet->prev_used = facet->used;
 
         in_port = get_ofp_port(ofproto, facet->flow.in_port.ofp_port);
-        if (in_port && in_port->tnl_port) {
+        if (in_port && in_port->is_tunnel) {
             netdev_vport_inc_rx(in_port->up.netdev, &stats);
         }
 
@@ -5030,6 +5045,8 @@ subfacet_install(struct subfacet *subfacet, const struct ofpbuf *odp_actions,
     enum subfacet_path path = facet->xout.slow ? SF_SLOW_PATH : SF_FAST_PATH;
     const struct nlattr *actions = odp_actions->data;
     size_t actions_len = odp_actions->size;
+    struct odputil_keybuf maskbuf;
+    struct ofpbuf mask;
 
     uint64_t slow_path_stub[128 / 8];
     enum dpif_flow_put_flags flags;
@@ -5046,8 +5063,12 @@ subfacet_install(struct subfacet *subfacet, const struct ofpbuf *odp_actions,
                           &actions, &actions_len);
     }
 
-    ret = dpif_flow_put(ofproto->backer->dpif, flags, subfacet->key,
-                        subfacet->key_len,  NULL, 0,
+    ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf);
+    odp_flow_key_from_mask(&mask, &facet->xout.wc.masks,
+                           &facet->flow, UINT32_MAX);
+
+    ret = dpif_flow_put(subfacet->backer->dpif, flags, subfacet->key,
+                        subfacet->key_len,  mask.data, mask.size,
                         actions, actions_len, stats);
 
     if (stats) {
@@ -5158,6 +5179,7 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto,
     }
 
     if (wc) {
+        memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type);
         wc->masks.nw_frag |= FLOW_NW_FRAG_MASK;
     }
 
@@ -5481,6 +5503,22 @@ update_mirror_stats(struct ofproto_dpif *ofproto, mirror_mask_t mirrors,
     }
 }
 
+tag_type
+calculate_flow_tag(struct ofproto_dpif *ofproto, const struct flow *flow,
+                   uint8_t table_id, struct rule_dpif *rule)
+{
+    if (table_id > 0 && table_id < N_TABLES) {
+        struct table_dpif *table = &ofproto->tables[table_id];
+        if (table->other_table) {
+            return (rule && rule->tag
+                    ? rule->tag
+                    : rule_calculate_tag(flow, &table->other_table->mask,
+                                         table->basis));
+        }
+    }
+
+    return 0;
+}
 \f
 /* Optimized flow revalidation.
  *
@@ -5764,9 +5802,12 @@ ofproto_unixctl_fdb_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
     ds_put_cstr(&ds, " port  VLAN  MAC                Age\n");
     LIST_FOR_EACH (e, lru_node, &ofproto->ml->lrus) {
         struct ofbundle *bundle = e->port.p;
-        ds_put_format(&ds, "%5d  %4d  "ETH_ADDR_FMT"  %3d\n",
-                      ofbundle_get_a_port(bundle)->odp_port,
-                      e->vlan, ETH_ADDR_ARGS(e->mac),
+        char name[OFP_MAX_PORT_NAME_LEN];
+
+        ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port,
+                               name, sizeof name);
+        ds_put_format(&ds, "%5s  %4d  "ETH_ADDR_FMT"  %3d\n",
+                      name, e->vlan, ETH_ADDR_ARGS(e->mac),
                       mac_entry_age(ofproto->ml, e));
     }
     unixctl_command_reply(conn, ds_cstr(&ds));
@@ -5871,7 +5912,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
 {
     const struct dpif_backer *backer;
     struct ofproto_dpif *ofproto;
-    struct ofpbuf odp_key;
+    struct ofpbuf odp_key, odp_mask;
     struct ofpbuf *packet;
     struct ds result;
     struct flow flow;
@@ -5881,6 +5922,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
     backer = NULL;
     ds_init(&result);
     ofpbuf_init(&odp_key, 0);
+    ofpbuf_init(&odp_mask, 0);
 
     /* Handle "-generate" or a hex string as the last argument. */
     if (!strcmp(argv[argc - 1], "-generate")) {
@@ -5901,7 +5943,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
      * bridge is specified. If function odp_flow_key_from_string()
      * returns 0, the flow is a odp_flow. If function
      * parse_ofp_exact_flow() returns 0, the flow is a br_flow. */
-    if (!odp_flow_from_string(argv[argc - 1], NULL, &odp_key, NULL)) {
+    if (!odp_flow_from_string(argv[argc - 1], NULL, &odp_key, &odp_mask)) {
         /* If the odp_flow is the second argument,
          * the datapath name is the first argument. */
         if (argc == 3) {
@@ -5981,6 +6023,7 @@ exit:
     ds_destroy(&result);
     ofpbuf_delete(packet);
     ofpbuf_uninit(&odp_key);
+    ofpbuf_uninit(&odp_mask);
 }
 
 void
@@ -6538,7 +6581,7 @@ vlandev_find(const struct ofproto_dpif *ofproto, ofp_port_t vlandev_ofp_port)
     struct vlan_splinter *vsp;
 
     HMAP_FOR_EACH_WITH_HASH (vsp, vlandev_node,
-                             hash_int(ofp_to_u16(vlandev_ofp_port), 0),
+                             hash_ofp_port(vlandev_ofp_port),
                              &ofproto->vlandev_map) {
         if (vsp->vlandev_ofp_port == vlandev_ofp_port) {
             return vsp;
@@ -6629,7 +6672,7 @@ vsp_add(struct ofport_dpif *port, ofp_port_t realdev_ofp_port, int vid)
 
         vsp = xmalloc(sizeof *vsp);
         hmap_insert(&ofproto->vlandev_map, &vsp->vlandev_node,
-                    hash_int(ofp_to_u16(port->up.ofp_port), 0));
+                    hash_ofp_port(port->up.ofp_port));
         hmap_insert(&ofproto->realdev_vid_map, &vsp->realdev_vid_node,
                     hash_realdev_vid(realdev_ofp_port, vid));
         vsp->realdev_ofp_port = realdev_ofp_port;
@@ -6654,8 +6697,7 @@ odp_port_to_ofport(const struct dpif_backer *backer, odp_port_t odp_port)
 {
     struct ofport_dpif *port;
 
-    HMAP_FOR_EACH_IN_BUCKET (port, odp_port_node,
-                             hash_int(odp_to_u32(odp_port), 0),
+    HMAP_FOR_EACH_IN_BUCKET (port, odp_port_node, hash_odp_port(odp_port),
                              &backer->odp_to_ofport_map) {
         if (port->odp_port == odp_port) {
             return port;
@@ -6791,4 +6833,8 @@ const struct ofproto_class ofproto_dpif_class = {
     forward_bpdu_changed,
     set_mac_table_config,
     set_realdev,
+    NULL,                       /* meter_get_features */
+    NULL,                       /* meter_set */
+    NULL,                       /* meter_get */
+    NULL,                       /* meter_del */
 };