ofproto-dpif-xlate: Take control of the qdscp map.
authorEthan Jackson <ethan@nicira.com>
Sat, 6 Jul 2013 17:25:06 +0000 (10:25 -0700)
committerEthan Jackson <ethan@nicira.com>
Sat, 3 Aug 2013 01:21:23 +0000 (18:21 -0700)
This will make locking easier in future patches.

Signed-off-by: Ethan Jackson <ethan@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
ofproto/ofproto-dpif-xlate.c
ofproto/ofproto-dpif-xlate.h
ofproto/ofproto-dpif.c
ofproto/ofproto-dpif.h

index 066de47..6ce30cb 100644 (file)
@@ -114,6 +114,8 @@ struct xport {
     enum ofputil_port_config config; /* OpenFlow port configuration. */
     int stp_port_no;                 /* STP port number or 0 if not in use. */
 
+    struct hmap skb_priorities;      /* Map of 'skb_priority_to_dscp's. */
+
     bool may_enable;                 /* May be enabled in bonds. */
     bool is_tunnel;                  /* Is a tunnel port. */
 
@@ -164,6 +166,16 @@ struct xlate_ctx {
  * The bundle's name and vlan mode are initialized in lookup_input_bundle() */
 static struct xbundle ofpp_none_bundle;
 
+/* Node in 'xport''s 'skb_priorities' map.  Used to maintain a map from
+ * 'priority' (the datapath's term for QoS queue) to the dscp bits which all
+ * traffic egressing the 'ofport' with that priority should be marked with. */
+struct skb_priority_to_dscp {
+    struct hmap_node hmap_node; /* Node in 'ofport_dpif''s 'skb_priorities'. */
+    uint32_t skb_priority;      /* Priority of this queue (see struct flow). */
+
+    uint8_t dscp;               /* DSCP bits to mark outgoing traffic with. */
+};
+
 static struct hmap xbridges = HMAP_INITIALIZER(&xbridges);
 static struct hmap xbundles = HMAP_INITIALIZER(&xbundles);
 static struct hmap xports = HMAP_INITIALIZER(&xports);
@@ -187,6 +199,11 @@ static struct xbridge *xbridge_lookup(const struct ofproto_dpif *);
 static struct xbundle *xbundle_lookup(const struct ofbundle *);
 static struct xport *xport_lookup(struct ofport_dpif *);
 static struct xport *get_ofp_port(const struct xbridge *, ofp_port_t ofp_port);
+static struct skb_priority_to_dscp *get_skb_priority(const struct xport *,
+                                                     uint32_t skb_priority);
+static void clear_skb_priorities(struct xport *);
+static bool dscp_from_skb_priority(const struct xport *, uint32_t skb_priority,
+                                   uint8_t *dscp);
 
 void
 xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
@@ -335,10 +352,12 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
                  odp_port_t odp_port, const struct netdev *netdev,
                  const struct cfm *cfm, const struct bfd *bfd,
                  struct ofport_dpif *peer, int stp_port_no,
+                 const struct ofproto_port_queue *qdscp_list, size_t n_qdscp,
                  enum ofputil_port_config config, bool is_tunnel,
                  bool may_enable)
 {
     struct xport *xport = xport_lookup(ofport);
+    size_t i;
 
     if (!xport) {
         xport = xzalloc(sizeof *xport);
@@ -346,6 +365,7 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
         xport->xbridge = xbridge_lookup(ofproto);
         xport->ofp_port = ofp_port;
 
+        hmap_init(&xport->skb_priorities);
         hmap_insert(&xports, &xport->hmap_node, hash_pointer(ofport, 0));
         hmap_insert(&xport->xbridge->xports, &xport->ofp_node,
                     hash_ofp_port(xport->ofp_port));
@@ -389,6 +409,24 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
     if (xport->xbundle) {
         list_insert(&xport->xbundle->xports, &xport->bundle_node);
     }
+
+    clear_skb_priorities(xport);
+    for (i = 0; i < n_qdscp; i++) {
+        struct skb_priority_to_dscp *pdscp;
+        uint32_t skb_priority;
+
+        if (ofproto_dpif_queue_to_priority(xport->xbridge->ofproto,
+                                           qdscp_list[i].queue,
+                                           &skb_priority)) {
+            continue;
+        }
+
+        pdscp = xmalloc(sizeof *pdscp);
+        pdscp->skb_priority = skb_priority;
+        pdscp->dscp = (qdscp_list[i].dscp << 2) & IP_DSCP_MASK;
+        hmap_insert(&xport->skb_priorities, &pdscp->hmap_node,
+                    hash_int(pdscp->skb_priority, 0));
+    }
 }
 
 void
@@ -409,6 +447,9 @@ xlate_ofport_remove(struct ofport_dpif *ofport)
         list_remove(&xport->bundle_node);
     }
 
+    clear_skb_priorities(xport);
+    hmap_destroy(&xport->skb_priorities);
+
     hmap_remove(&xports, &xport->hmap_node);
     hmap_remove(&xport->xbridge->xports, &xport->ofp_node);
 
@@ -1362,8 +1403,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
     flow_skb_mark = flow->skb_mark;
     flow_nw_tos = flow->nw_tos;
 
-    if (ofproto_dpif_dscp_from_priority(xport->ofport, flow->skb_priority,
-                                        &dscp)) {
+    if (dscp_from_skb_priority(xport, flow->skb_priority, &dscp)) {
         wc->masks.nw_tos |= IP_ECN_MASK;
         flow->nw_tos &= ~IP_DSCP_MASK;
         flow->nw_tos |= dscp;
@@ -2261,6 +2301,41 @@ xlate_out_copy(struct xlate_out *dst, const struct xlate_out *src)
                src->odp_actions.size);
 }
 \f
+static struct skb_priority_to_dscp *
+get_skb_priority(const struct xport *xport, uint32_t skb_priority)
+{
+    struct skb_priority_to_dscp *pdscp;
+    uint32_t hash;
+
+    hash = hash_int(skb_priority, 0);
+    HMAP_FOR_EACH_IN_BUCKET (pdscp, hmap_node, hash, &xport->skb_priorities) {
+        if (pdscp->skb_priority == skb_priority) {
+            return pdscp;
+        }
+    }
+    return NULL;
+}
+
+static bool
+dscp_from_skb_priority(const struct xport *xport, uint32_t skb_priority,
+                       uint8_t *dscp)
+{
+    struct skb_priority_to_dscp *pdscp = get_skb_priority(xport, skb_priority);
+    *dscp = pdscp ? pdscp->dscp : 0;
+    return pdscp != NULL;
+}
+
+static void
+clear_skb_priorities(struct xport *xport)
+{
+    struct skb_priority_to_dscp *pdscp, *next;
+
+    HMAP_FOR_EACH_SAFE (pdscp, next, hmap_node, &xport->skb_priorities) {
+        hmap_remove(&xport->skb_priorities, &pdscp->hmap_node);
+        free(pdscp);
+    }
+}
+
 static bool
 actions_output_to_local_port(const struct xlate_ctx *ctx)
 {
index 3ce5aa9..39eb481 100644 (file)
@@ -127,8 +127,9 @@ void xlate_ofport_set(struct ofproto_dpif *, struct ofbundle *,
                       struct ofport_dpif *, ofp_port_t, odp_port_t,
                       const struct netdev *, const struct cfm *,
                       const struct bfd *, struct ofport_dpif *peer,
-                      int stp_port_no, enum ofputil_port_config,
-                      bool is_tunnel, bool may_enable);
+                      int stp_port_no, const struct ofproto_port_queue *qdscp,
+                      size_t n_qdscp, enum ofputil_port_config, bool is_tunnel,
+                      bool may_enable);
 void xlate_ofport_remove(struct ofport_dpif *);
 
 void xlate_actions(struct xlate_in *, struct xlate_out *);
index 56b1796..ce783f0 100644 (file)
@@ -298,7 +298,9 @@ struct ofport_dpif {
     enum stp_state stp_state;   /* Always STP_DISABLED if STP not in use. */
     long long int stp_state_entered;
 
-    struct hmap priorities;     /* Map of attached 'priority_to_dscp's. */
+    /* Queue to DSCP mapping. */
+    struct ofproto_port_queue *qdscp;
+    size_t n_qdscp;
 
     /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
      *
@@ -310,16 +312,6 @@ struct ofport_dpif {
     int vlandev_vid;
 };
 
-/* Node in 'ofport_dpif''s 'priorities' map.  Used to maintain a map from
- * 'priority' (the datapath's term for QoS queue) to the dscp bits which all
- * traffic egressing the 'ofport' with that priority should be marked with. */
-struct priority_to_dscp {
-    struct hmap_node hmap_node; /* Node in 'ofport_dpif''s 'priorities' map. */
-    uint32_t priority;          /* Priority of this queue (see struct flow). */
-
-    uint8_t dscp;               /* DSCP bits to mark outgoing traffic with. */
-};
-
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
  *
  * This is deprecated.  It is only for compatibility with broken device drivers
@@ -355,7 +347,6 @@ static void port_run_fast(struct ofport_dpif *);
 static void port_wait(struct ofport_dpif *);
 static int set_bfd(struct ofport *, const struct smap *);
 static int set_cfm(struct ofport *, const struct cfm_settings *);
-static void ofport_clear_priorities(struct ofport_dpif *);
 static void ofport_update_peer(struct ofport_dpif *);
 static void run_fast_rl(void);
 
@@ -794,6 +785,7 @@ type_run(const char *type)
                                  ofport->up.ofp_port, ofport->odp_port,
                                  ofport->up.netdev, ofport->cfm,
                                  ofport->bfd, ofport->peer, stp_port,
+                                 ofport->qdscp, ofport->n_qdscp,
                                  ofport->up.pp.config, ofport->is_tunnel,
                                  ofport->may_enable);
             }
@@ -1688,7 +1680,8 @@ port_construct(struct ofport *port_)
     port->stp_state = STP_DISABLED;
     port->is_tunnel = false;
     port->peer = NULL;
-    hmap_init(&port->priorities);
+    port->qdscp = NULL;
+    port->n_qdscp = 0;
     port->realdev_ofp_port = 0;
     port->vlandev_vid = 0;
     port->carrier_seq = netdev_get_carrier_resets(netdev);
@@ -1782,8 +1775,7 @@ port_destruct(struct ofport *port_)
         dpif_sflow_del_port(ofproto->sflow, port->odp_port);
     }
 
-    ofport_clear_priorities(port);
-    hmap_destroy(&port->priorities);
+    free(port->qdscp);
 }
 
 static void
@@ -2186,88 +2178,24 @@ ofproto_dpif_queue_to_priority(const struct ofproto_dpif *ofproto,
     return dpif_queue_to_priority(ofproto->backer->dpif, queue_id, priority);
 }
 
-static struct priority_to_dscp *
-get_priority(const struct ofport_dpif *ofport, uint32_t priority)
-{
-    struct priority_to_dscp *pdscp;
-    uint32_t hash;
-
-    hash = hash_int(priority, 0);
-    HMAP_FOR_EACH_IN_BUCKET (pdscp, hmap_node, hash, &ofport->priorities) {
-        if (pdscp->priority == priority) {
-            return pdscp;
-        }
-    }
-    return NULL;
-}
-
-bool
-ofproto_dpif_dscp_from_priority(const struct ofport_dpif *ofport,
-                                uint32_t priority, uint8_t *dscp)
-{
-    struct priority_to_dscp *pdscp = get_priority(ofport, priority);
-    *dscp = pdscp ? pdscp->dscp : 0;
-    return pdscp != NULL;
-}
-
-static void
-ofport_clear_priorities(struct ofport_dpif *ofport)
-{
-    struct priority_to_dscp *pdscp, *next;
-
-    HMAP_FOR_EACH_SAFE (pdscp, next, hmap_node, &ofport->priorities) {
-        hmap_remove(&ofport->priorities, &pdscp->hmap_node);
-        free(pdscp);
-    }
-}
-
 static int
-set_queues(struct ofport *ofport_,
-           const struct ofproto_port_queue *qdscp_list,
+set_queues(struct ofport *ofport_, const struct ofproto_port_queue *qdscp,
            size_t n_qdscp)
 {
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
-    struct hmap new = HMAP_INITIALIZER(&new);
-    size_t i;
-
-    for (i = 0; i < n_qdscp; i++) {
-        struct priority_to_dscp *pdscp;
-        uint32_t priority;
-        uint8_t dscp;
-
-        dscp = (qdscp_list[i].dscp << 2) & IP_DSCP_MASK;
-        if (dpif_queue_to_priority(ofproto->backer->dpif, qdscp_list[i].queue,
-                                   &priority)) {
-            continue;
-        }
-
-        pdscp = get_priority(ofport, priority);
-        if (pdscp) {
-            hmap_remove(&ofport->priorities, &pdscp->hmap_node);
-        } else {
-            pdscp = xmalloc(sizeof *pdscp);
-            pdscp->priority = priority;
-            pdscp->dscp = dscp;
-            ofproto->backer->need_revalidate = REV_RECONFIGURE;
-        }
 
-        if (pdscp->dscp != dscp) {
-            pdscp->dscp = dscp;
-            ofproto->backer->need_revalidate = REV_RECONFIGURE;
-        }
-
-        hmap_insert(&new, &pdscp->hmap_node, hash_int(pdscp->priority, 0));
-    }
-
-    if (!hmap_is_empty(&ofport->priorities)) {
-        ofport_clear_priorities(ofport);
+    if (ofport->n_qdscp != n_qdscp
+        || (n_qdscp && memcmp(ofport->qdscp, qdscp,
+                              n_qdscp * sizeof *qdscp))) {
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
+        free(ofport->qdscp);
+        ofport->qdscp = n_qdscp
+            ? xmemdup(qdscp, n_qdscp * sizeof *qdscp)
+            : NULL;
+        ofport->n_qdscp = n_qdscp;
     }
 
-    hmap_swap(&new, &ofport->priorities);
-    hmap_destroy(&new);
-
     return 0;
 }
 \f
index 9e8a107..f67b88d 100644 (file)
@@ -74,8 +74,6 @@ ofp_port_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
                                   ofp_port_t realdev_ofp_port,
                                   ovs_be16 vlan_tci);
 
-bool ofproto_dpif_dscp_from_priority(const struct ofport_dpif *,
-                                     uint32_t priority, uint8_t *dscp);
 int ofproto_dpif_queue_to_priority(const struct ofproto_dpif *,
                                    uint32_t queue_id, uint32_t *priority);