From 55954f6e14ecdbd972294a4a8ed9f6f01cbffa9c Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Sat, 6 Jul 2013 10:25:06 -0700 Subject: [PATCH 1/1] ofproto-dpif-xlate: Take control of the qdscp map. This will make locking easier in future patches. Signed-off-by: Ethan Jackson Acked-by: Ben Pfaff --- ofproto/ofproto-dpif-xlate.c | 79 +++++++++++++++++++++++++- ofproto/ofproto-dpif-xlate.h | 5 +- ofproto/ofproto-dpif.c | 104 ++++++----------------------------- ofproto/ofproto-dpif.h | 2 - 4 files changed, 96 insertions(+), 94 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 066de4702..6ce30cb61 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -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); } +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) { diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 3ce5aa932..39eb4818e 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -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 *); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 56b17967e..ce783f0a3 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -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; } diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index 9e8a10705..f67b88d14 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -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); -- 2.43.0