2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 14:25:26 +00:00

odp-util: Pass down flow netlink attributes when translating masks.

Sometimes we need to look at flow fields to understand how to parse
an attribute. However, masks don't have this information - just the
mask on the field. We already use the translated flow structure for
this purpose but this isn't always enough since sometimes we actually
need the raw netlink information. Fortunately, that is also readily
available so this passes it down from the appropriate callers.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Jesse Gross
2015-06-19 13:54:13 -07:00
parent 4531547f4a
commit ec1f6f327e
6 changed files with 53 additions and 21 deletions

View File

@@ -796,7 +796,8 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
struct minimatch minimatch; struct minimatch minimatch;
odp_flow_key_to_flow(f.key, f.key_len, &flow); odp_flow_key_to_flow(f.key, f.key_len, &flow);
odp_flow_key_to_mask(f.mask, f.mask_len, &wc.masks, &flow); odp_flow_key_to_mask(f.mask, f.mask_len, f.key, f.key_len,
&wc.masks, &flow);
match_init(&match, &flow, &wc); match_init(&match, &flow, &wc);
match_init(&match_filter, &flow_filter, &wc); match_init(&match_filter, &flow_filter, &wc);

View File

@@ -1842,6 +1842,7 @@ dp_netdev_flow_to_dpif_flow(const struct dp_netdev_flow *netdev_flow,
offset = mask_buf->size; offset = mask_buf->size;
flow->mask = ofpbuf_tail(mask_buf); flow->mask = ofpbuf_tail(mask_buf);
odp_parms.odp_in_port = wc.masks.in_port.odp_port; odp_parms.odp_in_port = wc.masks.in_port.odp_port;
odp_parms.key_buf = key_buf;
odp_flow_key_from_mask(&odp_parms, mask_buf); odp_flow_key_from_mask(&odp_parms, mask_buf);
flow->mask_len = mask_buf->size - offset; flow->mask_len = mask_buf->size - offset;
@@ -1866,7 +1867,8 @@ dpif_netdev_mask_from_nlattrs(const struct nlattr *key, uint32_t key_len,
if (mask_key_len) { if (mask_key_len) {
enum odp_key_fitness fitness; enum odp_key_fitness fitness;
fitness = odp_flow_key_to_mask(mask_key, mask_key_len, mask, flow); fitness = odp_flow_key_to_mask(mask_key, mask_key_len, key, key_len,
mask, flow);
if (fitness) { if (fitness) {
/* This should not happen: it indicates that /* This should not happen: it indicates that
* odp_flow_key_from_mask() and odp_flow_key_to_mask() * odp_flow_key_from_mask() and odp_flow_key_to_mask()

View File

@@ -1350,8 +1350,12 @@ parse_geneve_opts(const struct nlattr *attr)
return 0; return 0;
} }
enum odp_key_fitness static enum odp_key_fitness
odp_tun_key_from_attr(const struct nlattr *attr, struct flow_tnl *tun) odp_tun_key_from_attr__(const struct nlattr *attr,
const struct nlattr *flow_attrs OVS_UNUSED,
size_t flow_attr_len OVS_UNUSED,
const struct flow_tnl *src_tun OVS_UNUSED,
struct flow_tnl *tun)
{ {
unsigned int left; unsigned int left;
const struct nlattr *a; const struct nlattr *a;
@@ -1446,8 +1450,16 @@ odp_tun_key_from_attr(const struct nlattr *attr, struct flow_tnl *tun)
return ODP_FIT_PERFECT; return ODP_FIT_PERFECT;
} }
enum odp_key_fitness
odp_tun_key_from_attr(const struct nlattr *attr, struct flow_tnl *tun)
{
return odp_tun_key_from_attr__(attr, NULL, 0, NULL, tun);
}
static void static void
tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key) tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
const struct flow_tnl *tun_flow_key OVS_UNUSED,
const struct ofpbuf *key_buf OVS_UNUSED)
{ {
size_t tun_key_ofs; size_t tun_key_ofs;
@@ -3428,7 +3440,8 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority); nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, data->skb_priority);
if (flow->tunnel.ip_dst || export_mask) { if (flow->tunnel.ip_dst || export_mask) {
tun_key_to_attr(buf, &data->tunnel); tun_key_to_attr(buf, &data->tunnel, &parms->flow->tunnel,
parms->key_buf);
} }
nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->pkt_mark); nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, data->pkt_mark);
@@ -3610,7 +3623,7 @@ odp_key_from_pkt_metadata(struct ofpbuf *buf, const struct pkt_metadata *md)
nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, md->skb_priority); nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, md->skb_priority);
if (md->tunnel.ip_dst) { if (md->tunnel.ip_dst) {
tun_key_to_attr(buf, &md->tunnel); tun_key_to_attr(buf, &md->tunnel, &md->tunnel, NULL);
} }
nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, md->pkt_mark); nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, md->pkt_mark);
@@ -4174,6 +4187,7 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
static enum odp_key_fitness static enum odp_key_fitness
odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len, odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
const struct nlattr *src_key, size_t src_key_len,
struct flow *flow, const struct flow *src_flow) struct flow *flow, const struct flow *src_flow)
{ {
const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1]; const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1];
@@ -4217,7 +4231,9 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TUNNEL)) { if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TUNNEL)) {
enum odp_key_fitness res; enum odp_key_fitness res;
res = odp_tun_key_from_attr(attrs[OVS_KEY_ATTR_TUNNEL], &flow->tunnel); res = odp_tun_key_from_attr__(attrs[OVS_KEY_ATTR_TUNNEL], src_key,
src_key_len, &src_flow->tunnel,
&flow->tunnel);
if (res == ODP_FIT_ERROR) { if (res == ODP_FIT_ERROR) {
return ODP_FIT_ERROR; return ODP_FIT_ERROR;
} else if (res == ODP_FIT_PERFECT) { } else if (res == ODP_FIT_PERFECT) {
@@ -4289,18 +4305,21 @@ enum odp_key_fitness
odp_flow_key_to_flow(const struct nlattr *key, size_t key_len, odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
struct flow *flow) struct flow *flow)
{ {
return odp_flow_key_to_flow__(key, key_len, flow, flow); return odp_flow_key_to_flow__(key, key_len, NULL, 0, flow, flow);
} }
/* Converts the 'key_len' bytes of OVS_KEY_ATTR_* attributes in 'key' to a mask /* Converts the 'mask_key_len' bytes of OVS_KEY_ATTR_* attributes in 'mask_key'
* structure in 'mask'. 'flow' must be a previously translated flow * to a mask structure in 'mask'. 'flow' must be a previously translated flow
* corresponding to 'mask'. Returns an ODP_FIT_* value that indicates how well * corresponding to 'mask' and similarly flow_key/flow_key_len must be the
* 'key' fits our expectations for what a flow key should contain. */ * attributes from that flow. Returns an ODP_FIT_* value that indicates how
* well 'key' fits our expectations for what a flow key should contain. */
enum odp_key_fitness enum odp_key_fitness
odp_flow_key_to_mask(const struct nlattr *key, size_t key_len, odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
const struct nlattr *flow_key, size_t flow_key_len,
struct flow *mask, const struct flow *flow) struct flow *mask, const struct flow *flow)
{ {
return odp_flow_key_to_flow__(key, key_len, mask, flow); return odp_flow_key_to_flow__(mask_key, mask_key_len, flow_key, flow_key_len,
mask, flow);
} }
/* Returns 'fitness' as a string, for use in debug messages. */ /* Returns 'fitness' as a string, for use in debug messages. */
@@ -4370,7 +4389,7 @@ odp_put_tunnel_action(const struct flow_tnl *tunnel,
struct ofpbuf *odp_actions) struct ofpbuf *odp_actions)
{ {
size_t offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SET); size_t offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SET);
tun_key_to_attr(odp_actions, tunnel); tun_key_to_attr(odp_actions, tunnel, tunnel, NULL);
nl_msg_end_nested(odp_actions, offset); nl_msg_end_nested(odp_actions, offset);
} }

View File

@@ -178,7 +178,13 @@ struct odp_flow_key_parms {
bool recirc; bool recirc;
/* Only used for mask translation: */ /* Only used for mask translation: */
size_t max_mpls_depth; size_t max_mpls_depth;
/* The netlink formatted version of the flow. It is used in cases where
* the mask cannot be constructed from the OVS internal representation
* and needs to see the original form. */
const struct ofpbuf *key_buf;
}; };
void odp_flow_key_from_flow(const struct odp_flow_key_parms *, struct ofpbuf *); void odp_flow_key_from_flow(const struct odp_flow_key_parms *, struct ofpbuf *);
@@ -207,7 +213,10 @@ enum odp_key_fitness {
}; };
enum odp_key_fitness odp_flow_key_to_flow(const struct nlattr *, size_t, enum odp_key_fitness odp_flow_key_to_flow(const struct nlattr *, size_t,
struct flow *); struct flow *);
enum odp_key_fitness odp_flow_key_to_mask(const struct nlattr *key, size_t len, enum odp_key_fitness odp_flow_key_to_mask(const struct nlattr *mask_key,
size_t mask_key_len,
const struct nlattr *flow_key,
size_t flow_key_len,
struct flow *mask, struct flow *mask,
const struct flow *flow); const struct flow *flow);
const char *odp_key_fitness_to_string(enum odp_key_fitness); const char *odp_key_fitness_to_string(enum odp_key_fitness);

View File

@@ -1386,6 +1386,7 @@ ukey_create_from_upcall(struct upcall *upcall)
odp_parms.odp_in_port = ODPP_NONE; odp_parms.odp_in_port = ODPP_NONE;
odp_parms.max_mpls_depth = ofproto_dpif_get_max_mpls_depth(upcall->ofproto); odp_parms.max_mpls_depth = ofproto_dpif_get_max_mpls_depth(upcall->ofproto);
odp_parms.recirc = recirc; odp_parms.recirc = recirc;
odp_parms.key_buf = &keybuf;
odp_flow_key_from_mask(&odp_parms, &maskbuf); odp_flow_key_from_mask(&odp_parms, &maskbuf);
} }
@@ -1736,8 +1737,8 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
goto exit; goto exit;
} }
if (odp_flow_key_to_mask(ukey->mask, ukey->mask_len, &dp_mask, &flow) if (odp_flow_key_to_mask(ukey->mask, ukey->mask_len, ukey->key,
== ODP_FIT_ERROR) { ukey->key_len, &dp_mask, &flow) == ODP_FIT_ERROR) {
goto exit; goto exit;
} }

View File

@@ -190,8 +190,8 @@ parse_filter(char *filter_parse)
struct minimatch minimatch; struct minimatch minimatch;
odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow); odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
odp_flow_key_to_mask(odp_mask.data, odp_mask.size, &wc.masks, odp_flow_key_to_mask(odp_mask.data, odp_mask.size, odp_key.data,
&flow); odp_key.size, &wc.masks, &flow);
match_init(&match, &flow, &wc); match_init(&match, &flow, &wc);
match_init(&match_filter, &flow_filter, &wc); match_init(&match_filter, &flow_filter, &wc);