mirror of
https://github.com/openvswitch/ovs
synced 2025-09-04 00:05:15 +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. */
|
enum ofputil_port_config config; /* OpenFlow port configuration. */
|
||||||
int stp_port_no; /* STP port number or 0 if not in use. */
|
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 may_enable; /* May be enabled in bonds. */
|
||||||
bool is_tunnel; /* Is a tunnel port. */
|
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() */
|
* The bundle's name and vlan mode are initialized in lookup_input_bundle() */
|
||||||
static struct xbundle ofpp_none_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 xbridges = HMAP_INITIALIZER(&xbridges);
|
||||||
static struct hmap xbundles = HMAP_INITIALIZER(&xbundles);
|
static struct hmap xbundles = HMAP_INITIALIZER(&xbundles);
|
||||||
static struct hmap xports = HMAP_INITIALIZER(&xports);
|
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 xbundle *xbundle_lookup(const struct ofbundle *);
|
||||||
static struct xport *xport_lookup(struct ofport_dpif *);
|
static struct xport *xport_lookup(struct ofport_dpif *);
|
||||||
static struct xport *get_ofp_port(const struct xbridge *, ofp_port_t ofp_port);
|
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
|
void
|
||||||
xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
|
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,
|
odp_port_t odp_port, const struct netdev *netdev,
|
||||||
const struct cfm *cfm, const struct bfd *bfd,
|
const struct cfm *cfm, const struct bfd *bfd,
|
||||||
struct ofport_dpif *peer, int stp_port_no,
|
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,
|
enum ofputil_port_config config, bool is_tunnel,
|
||||||
bool may_enable)
|
bool may_enable)
|
||||||
{
|
{
|
||||||
struct xport *xport = xport_lookup(ofport);
|
struct xport *xport = xport_lookup(ofport);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (!xport) {
|
if (!xport) {
|
||||||
xport = xzalloc(sizeof *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->xbridge = xbridge_lookup(ofproto);
|
||||||
xport->ofp_port = ofp_port;
|
xport->ofp_port = ofp_port;
|
||||||
|
|
||||||
|
hmap_init(&xport->skb_priorities);
|
||||||
hmap_insert(&xports, &xport->hmap_node, hash_pointer(ofport, 0));
|
hmap_insert(&xports, &xport->hmap_node, hash_pointer(ofport, 0));
|
||||||
hmap_insert(&xport->xbridge->xports, &xport->ofp_node,
|
hmap_insert(&xport->xbridge->xports, &xport->ofp_node,
|
||||||
hash_ofp_port(xport->ofp_port));
|
hash_ofp_port(xport->ofp_port));
|
||||||
@@ -389,6 +409,24 @@ xlate_ofport_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
|
|||||||
if (xport->xbundle) {
|
if (xport->xbundle) {
|
||||||
list_insert(&xport->xbundle->xports, &xport->bundle_node);
|
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
|
void
|
||||||
@@ -409,6 +447,9 @@ xlate_ofport_remove(struct ofport_dpif *ofport)
|
|||||||
list_remove(&xport->bundle_node);
|
list_remove(&xport->bundle_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_skb_priorities(xport);
|
||||||
|
hmap_destroy(&xport->skb_priorities);
|
||||||
|
|
||||||
hmap_remove(&xports, &xport->hmap_node);
|
hmap_remove(&xports, &xport->hmap_node);
|
||||||
hmap_remove(&xport->xbridge->xports, &xport->ofp_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_skb_mark = flow->skb_mark;
|
||||||
flow_nw_tos = flow->nw_tos;
|
flow_nw_tos = flow->nw_tos;
|
||||||
|
|
||||||
if (ofproto_dpif_dscp_from_priority(xport->ofport, flow->skb_priority,
|
if (dscp_from_skb_priority(xport, flow->skb_priority, &dscp)) {
|
||||||
&dscp)) {
|
|
||||||
wc->masks.nw_tos |= IP_ECN_MASK;
|
wc->masks.nw_tos |= IP_ECN_MASK;
|
||||||
flow->nw_tos &= ~IP_DSCP_MASK;
|
flow->nw_tos &= ~IP_DSCP_MASK;
|
||||||
flow->nw_tos |= dscp;
|
flow->nw_tos |= dscp;
|
||||||
@@ -2261,6 +2301,41 @@ xlate_out_copy(struct xlate_out *dst, const struct xlate_out *src)
|
|||||||
src->odp_actions.size);
|
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
|
static bool
|
||||||
actions_output_to_local_port(const struct xlate_ctx *ctx)
|
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,
|
struct ofport_dpif *, ofp_port_t, odp_port_t,
|
||||||
const struct netdev *, const struct cfm *,
|
const struct netdev *, const struct cfm *,
|
||||||
const struct bfd *, struct ofport_dpif *peer,
|
const struct bfd *, struct ofport_dpif *peer,
|
||||||
int stp_port_no, enum ofputil_port_config,
|
int stp_port_no, const struct ofproto_port_queue *qdscp,
|
||||||
bool is_tunnel, bool may_enable);
|
size_t n_qdscp, enum ofputil_port_config, bool is_tunnel,
|
||||||
|
bool may_enable);
|
||||||
void xlate_ofport_remove(struct ofport_dpif *);
|
void xlate_ofport_remove(struct ofport_dpif *);
|
||||||
|
|
||||||
void xlate_actions(struct xlate_in *, struct xlate_out *);
|
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. */
|
enum stp_state stp_state; /* Always STP_DISABLED if STP not in use. */
|
||||||
long long int stp_state_entered;
|
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.)
|
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
|
||||||
*
|
*
|
||||||
@@ -310,16 +312,6 @@ struct ofport_dpif {
|
|||||||
int vlandev_vid;
|
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.)
|
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
|
||||||
*
|
*
|
||||||
* This is deprecated. It is only for compatibility with broken device drivers
|
* 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 void port_wait(struct ofport_dpif *);
|
||||||
static int set_bfd(struct ofport *, const struct smap *);
|
static int set_bfd(struct ofport *, const struct smap *);
|
||||||
static int set_cfm(struct ofport *, const struct cfm_settings *);
|
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 ofport_update_peer(struct ofport_dpif *);
|
||||||
static void run_fast_rl(void);
|
static void run_fast_rl(void);
|
||||||
|
|
||||||
@@ -794,6 +785,7 @@ type_run(const char *type)
|
|||||||
ofport->up.ofp_port, ofport->odp_port,
|
ofport->up.ofp_port, ofport->odp_port,
|
||||||
ofport->up.netdev, ofport->cfm,
|
ofport->up.netdev, ofport->cfm,
|
||||||
ofport->bfd, ofport->peer, stp_port,
|
ofport->bfd, ofport->peer, stp_port,
|
||||||
|
ofport->qdscp, ofport->n_qdscp,
|
||||||
ofport->up.pp.config, ofport->is_tunnel,
|
ofport->up.pp.config, ofport->is_tunnel,
|
||||||
ofport->may_enable);
|
ofport->may_enable);
|
||||||
}
|
}
|
||||||
@@ -1688,7 +1680,8 @@ port_construct(struct ofport *port_)
|
|||||||
port->stp_state = STP_DISABLED;
|
port->stp_state = STP_DISABLED;
|
||||||
port->is_tunnel = false;
|
port->is_tunnel = false;
|
||||||
port->peer = NULL;
|
port->peer = NULL;
|
||||||
hmap_init(&port->priorities);
|
port->qdscp = NULL;
|
||||||
|
port->n_qdscp = 0;
|
||||||
port->realdev_ofp_port = 0;
|
port->realdev_ofp_port = 0;
|
||||||
port->vlandev_vid = 0;
|
port->vlandev_vid = 0;
|
||||||
port->carrier_seq = netdev_get_carrier_resets(netdev);
|
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);
|
dpif_sflow_del_port(ofproto->sflow, port->odp_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
ofport_clear_priorities(port);
|
free(port->qdscp);
|
||||||
hmap_destroy(&port->priorities);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
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
|
static int
|
||||||
set_queues(struct ofport *ofport_,
|
set_queues(struct ofport *ofport_, const struct ofproto_port_queue *qdscp,
|
||||||
const struct ofproto_port_queue *qdscp_list,
|
|
||||||
size_t n_qdscp)
|
size_t n_qdscp)
|
||||||
{
|
{
|
||||||
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
|
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
|
||||||
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
|
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++) {
|
if (ofport->n_qdscp != n_qdscp
|
||||||
struct priority_to_dscp *pdscp;
|
|| (n_qdscp && memcmp(ofport->qdscp, qdscp,
|
||||||
uint32_t priority;
|
n_qdscp * sizeof *qdscp))) {
|
||||||
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);
|
|
||||||
ofproto->backer->need_revalidate = REV_RECONFIGURE;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -74,8 +74,6 @@ ofp_port_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
|
|||||||
ofp_port_t realdev_ofp_port,
|
ofp_port_t realdev_ofp_port,
|
||||||
ovs_be16 vlan_tci);
|
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 *,
|
int ofproto_dpif_queue_to_priority(const struct ofproto_dpif *,
|
||||||
uint32_t queue_id, uint32_t *priority);
|
uint32_t queue_id, uint32_t *priority);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user