unaligned: Add unaligned accessors for ovs_be<N> data.
[openvswitch] / ofproto / ofproto.c
index 2857757295295dc90eea6a5870134f4b980a801e..c2c48e12bccbb55df556fef8a7d65ba86330dc3b 100644 (file)
@@ -1515,7 +1515,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;
         }
 
@@ -1618,9 +1621,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 +2788,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 +2801,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 +2895,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;
 
@@ -4461,6 +4462,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)) {