mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 14:25:26 +00:00
ofproto-dpif-xlate: Take control of the qdscp map.
This will make locking easier in future patches. Signed-off-by: Ethan Jackson <ethan@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
@@ -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 *);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user