2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-29 15:28:56 +00:00

datapath: Describe policy for extending flow key, implement needed changes.

When the datapath was converted to use Netlink attributes for describing
flow keys, I had a vague idea of how it could be smoothly extensible, but
I didn't actually implement extensibility or carefully think it through.
This commit adds a document that describes how flow keys can be extended
in a compatible fashion and adapts the existing interface to match what
it says.

This commit doesn't actually implement extensibility.  I already have a
separate patch series out for that.  This patch series borrows from that
one heavily, but the extensibility series will need to be reworked
somewhat once this one is in.

This commit is only lightly tested because I don't have a good test setup
for VLANs.

Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
This commit is contained in:
Ben Pfaff
2011-11-14 15:56:43 -08:00
parent 34118caede
commit fea393b1d6
11 changed files with 527 additions and 289 deletions

View File

@@ -844,10 +844,11 @@ void flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
const u32 ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
[OVS_KEY_ATTR_ENCAP] = 0,
[OVS_KEY_ATTR_PRIORITY] = sizeof(u32),
[OVS_KEY_ATTR_IN_PORT] = sizeof(u32),
[OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet),
[OVS_KEY_ATTR_8021Q] = sizeof(struct ovs_key_8021q),
[OVS_KEY_ATTR_VLAN] = sizeof(__be16),
[OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16),
[OVS_KEY_ATTR_IPV4] = sizeof(struct ovs_key_ipv4),
[OVS_KEY_ATTR_IPV6] = sizeof(struct ovs_key_ipv6),
@@ -968,26 +969,13 @@ static int ipv6_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_len,
return 0;
}
/**
* flow_from_nlattrs - parses Netlink attributes into a flow key.
* @swkey: receives the extracted flow key.
* @key_lenp: number of bytes used in @swkey.
* @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
* sequence.
*/
int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
const struct nlattr *attr)
static int parse_flow_nlattrs(const struct nlattr *attr,
const struct nlattr *a[], u64 *attrsp)
{
const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
const struct ovs_key_ethernet *eth_key;
const struct nlattr *nla;
int key_len;
u64 attrs;
int rem;
memset(swkey, 0, sizeof(struct sw_flow_key));
key_len = SW_FLOW_KEY_OFFSET(eth);
attrs = 0;
nla_for_each_nested(nla, attr, rem) {
u16 type = nla_type(nla);
@@ -1001,6 +989,33 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
if (rem)
return -EINVAL;
*attrsp = attrs;
return 0;
}
/**
* flow_from_nlattrs - parses Netlink attributes into a flow key.
* @swkey: receives the extracted flow key.
* @key_lenp: number of bytes used in @swkey.
* @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
* sequence.
*/
int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
const struct nlattr *attr)
{
const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
const struct ovs_key_ethernet *eth_key;
int key_len;
u64 attrs;
int err;
memset(swkey, 0, sizeof(struct sw_flow_key));
key_len = SW_FLOW_KEY_OFFSET(eth);
err = parse_flow_nlattrs(attr, a, &attrs);
if (err)
return err;
/* Metadata attributes. */
if (attrs & (1 << OVS_KEY_ATTR_PRIORITY)) {
swkey->phy.priority = nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]);
@@ -1030,18 +1045,18 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
memcpy(swkey->eth.src, eth_key->eth_src, ETH_ALEN);
memcpy(swkey->eth.dst, eth_key->eth_dst, ETH_ALEN);
if (attrs & (1 << OVS_KEY_ATTR_8021Q)) {
const struct ovs_key_8021q *q_key;
q_key = nla_data(a[OVS_KEY_ATTR_8021Q]);
/* Only standard 0x8100 VLANs currently supported. */
if (q_key->q_tpid != htons(ETH_P_8021Q))
if (attrs == ((1 << OVS_KEY_ATTR_VLAN) |
(1 << OVS_KEY_ATTR_ETHERTYPE) |
(1 << OVS_KEY_ATTR_ENCAP)) &&
nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]) == htons(ETH_P_8021Q)) {
swkey->eth.tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
if (swkey->eth.tci & htons(VLAN_TAG_PRESENT))
return -EINVAL;
if (q_key->q_tci & htons(VLAN_TAG_PRESENT))
return -EINVAL;
swkey->eth.tci = q_key->q_tci | htons(VLAN_TAG_PRESENT);
swkey->eth.tci |= htons(VLAN_TAG_PRESENT);
attrs &= ~(1 << OVS_KEY_ATTR_8021Q);
err = parse_flow_nlattrs(a[OVS_KEY_ATTR_ENCAP], a, &attrs);
if (err)
return err;
}
if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
@@ -1072,7 +1087,7 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
swkey->ipv4.addr.dst = ipv4_key->ipv4_dst;
if (swkey->ip.frag != OVS_FRAG_TYPE_LATER) {
int err = ipv4_flow_from_nlattrs(swkey, &key_len, a, &attrs);
err = ipv4_flow_from_nlattrs(swkey, &key_len, a, &attrs);
if (err)
return err;
}
@@ -1098,7 +1113,7 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
sizeof(swkey->ipv6.addr.dst));
if (swkey->ip.frag != OVS_FRAG_TYPE_LATER) {
int err = ipv6_flow_from_nlattrs(swkey, &key_len, a, &attrs);
err = ipv6_flow_from_nlattrs(swkey, &key_len, a, &attrs);
if (err)
return err;
}
@@ -1181,7 +1196,7 @@ int flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, __be64 *tun_id,
int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
{
struct ovs_key_ethernet *eth_key;
struct nlattr *nla;
struct nlattr *nla, *encap;
if (swkey->phy.priority)
NLA_PUT_U32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority);
@@ -1200,15 +1215,16 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
memcpy(eth_key->eth_dst, swkey->eth.dst, ETH_ALEN);
if (swkey->eth.tci != htons(0)) {
struct ovs_key_8021q q_key;
q_key.q_tpid = htons(ETH_P_8021Q);
q_key.q_tci = swkey->eth.tci & ~htons(VLAN_TAG_PRESENT);
NLA_PUT(skb, OVS_KEY_ATTR_8021Q, sizeof(q_key), &q_key);
NLA_PUT_BE16(skb, OVS_KEY_ATTR_ETHERTYPE, htons(ETH_P_8021Q));
NLA_PUT_BE16(skb, OVS_KEY_ATTR_VLAN,
swkey->eth.tci & ~htons(VLAN_TAG_PRESENT));
encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
} else {
encap = NULL;
}
if (swkey->eth.type == htons(ETH_P_802_2))
return 0;
goto unencap;
NLA_PUT_BE16(skb, OVS_KEY_ATTR_ETHERTYPE, swkey->eth.type);
@@ -1326,6 +1342,10 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
}
}
unencap:
if (encap)
nla_nest_end(skb, encap);
return 0;
nla_put_failure: