datapath: Make adding and attaching a vport a single step.
[sliver-openvswitch.git] / ofproto / ofproto.c
index bf4a51f..7e83b0b 100644 (file)
 
 VLOG_DEFINE_THIS_MODULE(ofproto);
 
+COVERAGE_DEFINE(facet_changed_rule);
+COVERAGE_DEFINE(facet_revalidate);
+COVERAGE_DEFINE(odp_overflow);
+COVERAGE_DEFINE(ofproto_agg_request);
+COVERAGE_DEFINE(ofproto_costly_flags);
+COVERAGE_DEFINE(ofproto_ctlr_action);
+COVERAGE_DEFINE(ofproto_del_rule);
+COVERAGE_DEFINE(ofproto_error);
+COVERAGE_DEFINE(ofproto_expiration);
+COVERAGE_DEFINE(ofproto_expired);
+COVERAGE_DEFINE(ofproto_flows_req);
+COVERAGE_DEFINE(ofproto_flush);
+COVERAGE_DEFINE(ofproto_invalidated);
+COVERAGE_DEFINE(ofproto_no_packet_in);
+COVERAGE_DEFINE(ofproto_ofconn_stuck);
+COVERAGE_DEFINE(ofproto_ofp2odp);
+COVERAGE_DEFINE(ofproto_packet_in);
+COVERAGE_DEFINE(ofproto_packet_out);
+COVERAGE_DEFINE(ofproto_queue_req);
+COVERAGE_DEFINE(ofproto_recv_openflow);
+COVERAGE_DEFINE(ofproto_reinit_ports);
+COVERAGE_DEFINE(ofproto_unexpected_rule);
+COVERAGE_DEFINE(ofproto_uninstallable);
+COVERAGE_DEFINE(ofproto_update_port);
+
 #include "sflow_api.h"
 
 struct ofport {
@@ -230,7 +255,7 @@ struct ofconn {
     struct list node;           /* In struct ofproto's "all_conns" list. */
     struct rconn *rconn;        /* OpenFlow connection. */
     enum ofconn_type type;      /* Type. */
-    int flow_format;            /* One of NXFF_*. */
+    enum nx_flow_format flow_format; /* Currently selected flow format. */
 
     /* OFPT_PACKET_IN related data. */
     struct rconn_packet_counter *packet_in_counter; /* # queued on 'rconn'. */
@@ -1291,7 +1316,7 @@ int
 ofproto_port_del(struct ofproto *ofproto, uint16_t odp_port)
 {
     struct ofport *ofport = get_port(ofproto, odp_port);
-    const char *name = ofport ? (char *) ofport->opp.name : "<unknown>";
+    const char *name = ofport ? ofport->opp.name : "<unknown>";
     int error;
 
     error = dpif_port_del(ofproto->dpif, odp_port);
@@ -1414,7 +1439,7 @@ reinit_ports(struct ofproto *p)
 
     svec_init(&devnames);
     HMAP_FOR_EACH (ofport, hmap_node, &p->ports) {
-        svec_add (&devnames, (char *) ofport->opp.name);
+        svec_add (&devnames, ofport->opp.name);
     }
     dpif_port_list(p->dpif, &odp_ports, &n_odp_ports);
     for (i = 0; i < n_odp_ports; i++) {
@@ -1440,6 +1465,7 @@ make_ofport(const struct odp_port *odp_port)
 
     memset(&netdev_options, 0, sizeof netdev_options);
     netdev_options.name = odp_port->devname;
+    netdev_options.type = odp_port->type;
     netdev_options.ethertype = NETDEV_ETH_TYPE_NONE;
 
     error = netdev_open(&netdev_options, &netdev);
@@ -1496,7 +1522,7 @@ ofport_equal(const struct ofport *a_, const struct ofport *b_)
     BUILD_ASSERT_DECL(sizeof *a == 48); /* Detect ofp_phy_port changes. */
     return (a->port_no == b->port_no
             && !memcmp(a->hw_addr, b->hw_addr, sizeof a->hw_addr)
-            && !strcmp((char *) a->name, (char *) b->name)
+            && !strcmp(a->name, b->name)
             && a->state == b->state
             && a->config == b->config
             && a->curr == b->curr
@@ -1515,7 +1541,10 @@ send_port_status(struct ofproto *p, const struct ofport *ofport,
         struct ofp_port_status *ops;
         struct ofpbuf *b;
 
-        if (!ofconn_receives_async_msgs(ofconn)) {
+        /* Primary controllers, even slaves, should always get port status
+           updates.  Otherwise obey ofconn_receives_async_msgs(). */
+        if (ofconn->type != OFCONN_PRIMARY
+            && !ofconn_receives_async_msgs(ofconn)) {
             continue;
         }
 
@@ -1530,7 +1559,7 @@ send_port_status(struct ofproto *p, const struct ofport *ofport,
 static void
 ofport_install(struct ofproto *p, struct ofport *ofport)
 {
-    const char *netdev_name = (const char *) ofport->opp.name;
+    const char *netdev_name = ofport->opp.name;
 
     netdev_monitor_add(p->netdev_monitor, ofport->netdev);
     hmap_insert(&p->ports, &ofport->hmap_node, hash_int(ofport->odp_port, 0));
@@ -1546,7 +1575,7 @@ ofport_remove(struct ofproto *p, struct ofport *ofport)
     netdev_monitor_remove(p->netdev_monitor, ofport->netdev);
     hmap_remove(&p->ports, &ofport->hmap_node);
     shash_delete(&p->port_by_name,
-                 shash_find(&p->port_by_name, (char *) ofport->opp.name));
+                 shash_find(&p->port_by_name, ofport->opp.name));
     if (p->sflow) {
         ofproto_sflow_del_port(p->sflow, ofport->odp_port);
     }
@@ -1618,9 +1647,9 @@ update_port(struct ofproto *p, const char *devname)
         return;
     } else if (old_ofport && new_ofport) {
         /* Most of the 'config' bits are OpenFlow soft state, but
-         * OFPPC_PORT_DOWN is maintained the kernel.  So transfer the OpenFlow
-         * bits from old_ofport.  (make_ofport() only sets OFPPC_PORT_DOWN and
-         * leaves the other bits 0.)  */
+         * OFPPC_PORT_DOWN is maintained by the kernel.  So transfer the
+         * OpenFlow bits from old_ofport.  (make_ofport() only sets
+         * OFPPC_PORT_DOWN and leaves the other bits 0.)  */
         new_ofport->opp.config |= old_ofport->opp.config & ~OFPPC_PORT_DOWN;
 
         if (ofport_equal(old_ofport, new_ofport)) {
@@ -2785,15 +2814,12 @@ xlate_set_queue_action(struct action_xlate_ctx *ctx,
 static void
 xlate_set_dl_tci(struct action_xlate_ctx *ctx)
 {
-    ovs_be16 dl_vlan = ctx->flow.dl_vlan;
-    uint8_t dl_vlan_pcp = ctx->flow.dl_vlan_pcp;
-
-    if (dl_vlan == htons(OFP_VLAN_NONE)) {
+    ovs_be16 tci = ctx->flow.vlan_tci;
+    if (!(tci & htons(VLAN_CFI))) {
         odp_actions_add(ctx->out, ODPAT_STRIP_VLAN);
     } else {
         union odp_action *oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
-        oa->dl_tci.tci = htons(ntohs(dl_vlan & htons(VLAN_VID_MASK))
-                               | (dl_vlan_pcp << VLAN_PCP_SHIFT));
+        oa->dl_tci.tci = tci & ~htons(VLAN_CFI);
     }
 }
 
@@ -2801,12 +2827,11 @@ static void
 xlate_reg_move_action(struct action_xlate_ctx *ctx,
                       const struct nx_action_reg_move *narm)
 {
-    ovs_be16 old_vlan = ctx->flow.dl_vlan;
-    uint8_t old_pcp = ctx->flow.dl_vlan_pcp;
+    ovs_be16 old_tci = ctx->flow.vlan_tci;
 
     nxm_execute_reg_move(narm, &ctx->flow);
 
-    if (ctx->flow.dl_vlan != old_vlan || ctx->flow.dl_vlan_pcp != old_pcp) {
+    if (ctx->flow.vlan_tci != old_tci) {
         xlate_set_dl_tci(ctx);
     }
 }
@@ -2896,18 +2921,20 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
             break;
 
         case OFPAT_SET_VLAN_VID:
-            ctx->flow.dl_vlan = ia->vlan_vid.vlan_vid;
+            ctx->flow.vlan_tci &= ~htons(VLAN_VID_MASK);
+            ctx->flow.vlan_tci |= ia->vlan_vid.vlan_vid | htons(VLAN_CFI);
             xlate_set_dl_tci(ctx);
             break;
 
         case OFPAT_SET_VLAN_PCP:
-            ctx->flow.dl_vlan_pcp = ia->vlan_pcp.vlan_pcp;
+            ctx->flow.vlan_tci &= ~htons(VLAN_PCP_MASK);
+            ctx->flow.vlan_tci |= htons(
+                (ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT) | VLAN_CFI);
             xlate_set_dl_tci(ctx);
             break;
 
         case OFPAT_STRIP_VLAN:
-            ctx->flow.dl_vlan = htons(OFP_VLAN_NONE);
-            ctx->flow.dl_vlan_pcp = 0;
+            ctx->flow.vlan_tci = htons(0);
             xlate_set_dl_tci(ctx);
             break;
 
@@ -3412,7 +3439,7 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
     ofs->length = htons(len);
     ofs->table_id = 0;
     ofs->pad = 0;
-    cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofs->match);
+    ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofs->match);
     calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
     ofs->cookie = rule->flow_cookie;
     ofs->priority = htons(rule->cr.priority);
@@ -3451,7 +3478,8 @@ handle_flow_stats_request(struct ofconn *ofconn,
         struct cls_rule target;
         struct rule *rule;
 
-        cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target);
+        ofputil_cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0,
+                                    &target);
         cls_cursor_init(&cursor, &ofconn->ofproto->cls, &target);
         CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
             put_ofp_flow_stats(ofconn, rule, fsr->out_port, &reply);
@@ -3543,7 +3571,7 @@ flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results)
     size_t act_len = sizeof *rule->actions * rule->n_actions;
 
     query_stats(ofproto, rule, &packet_count, &byte_count);
-    cls_rule_to_match(&rule->cr, NXFF_OPENFLOW10, &match);
+    ofputil_cls_rule_to_match(&rule->cr, NXFF_OPENFLOW10, &match);
 
     ds_put_format(results, "duration=%llds, ",
                   (time_msec() - rule->created) / 1000);
@@ -3624,7 +3652,8 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
     }
     request = (struct ofp_aggregate_stats_request *) osr->body;
 
-    cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0, &target);
+    ofputil_cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0,
+                                &target);
 
     msg = start_ofp_stats_reply(osr, sizeof *reply);
     reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg);
@@ -4183,8 +4212,8 @@ handle_ofpt_flow_mod(struct ofconn *ofconn, struct ofp_header *oh)
     }
 
     /* Translate the message. */
-    cls_rule_from_match(&ofm->match, ntohs(ofm->priority), ofconn->flow_format,
-                        ofm->cookie, &fm.cr);
+    ofputil_cls_rule_from_match(&ofm->match, ntohs(ofm->priority),
+                                ofconn->flow_format, ofm->cookie, &fm.cr);
     fm.cookie = ofm->cookie;
     fm.command = ntohs(ofm->command);
     fm.idle_timeout = ntohs(ofm->idle_timeout);
@@ -4459,6 +4488,11 @@ handle_odp_miss_msg(struct ofproto *p, struct ofpbuf *packet)
     payload.size = msg->length - sizeof *msg;
     flow_extract(&payload, msg->arg, msg->port, &flow);
 
+    packet->l2 = payload.l2;
+    packet->l3 = payload.l3;
+    packet->l4 = payload.l4;
+    packet->l7 = payload.l7;
+
     /* Check with in-band control to see if this packet should be sent
      * to the local port regardless of the flow table. */
     if (in_band_msg_in_hook(p->in_band, &flow, &payload)) {
@@ -4813,7 +4847,7 @@ compose_ofp_flow_removed(struct ofconn *ofconn, const struct rule *rule,
     struct ofpbuf *buf;
 
     ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf);
-    cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofr->match);
+    ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofr->match);
     ofr->cookie = rule->flow_cookie;
     ofr->priority = htons(rule->cr.priority);
     ofr->reason = reason;