The openvswitch exchange the key with key netlink message between the kernel data path and user space flow tables. The key fields are defined as key attributes.
Signed-off-by: Johnson Li <johnson...@intel.com> diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index 6ffcc53..15685c7 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -147,6 +147,13 @@ static bool match_validate(const struct sw_flow_match *match, | (1ULL << OVS_KEY_ATTR_IN_PORT) | (1ULL << OVS_KEY_ATTR_ETHERTYPE)); + /* Network Service Header */ + if (match->key->nsh.md_type) { + key_expected |= 1 << OVS_KEY_ATTR_NSH; + if (match->mask) + mask_allowed |= 1 << OVS_KEY_ATTR_NSH; + } + /* Check key attributes. */ if (match->key->eth.type == htons(ETH_P_ARP) || match->key->eth.type == htons(ETH_P_RARP)) { @@ -279,12 +286,25 @@ size_t ovs_tun_key_attr_size(void) + nla_total_size(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */ } +size_t ovs_nsh_key_attr_size(void) +{ + return nla_total_size(1) /* OVS_NSH_KEY_ATTR_FLAGS */ + + nla_total_size(1) /* OVS_NSH_KEY_ATTR_MD_TYPE */ + + nla_total_size(1) /* OVS_NSH_KEY_ATTR_NEXT_PROTO */ + + nla_total_size(1) /* OVS_NSH_KEY_ATTR_NSI */ + + nla_total_size(4) /* OVS_NSH_KEY_ATTR_NSP */ + + nla_total_size(4) /* OVS_NSH_KEY_ATTR_NSHC1 */ + + nla_total_size(4) /* OVS_NSH_KEY_ATTR_NSHC2 */ + + nla_total_size(4) /* OVS_NSH_KEY_ATTR_NSHC3 */ + + nla_total_size(4); /* OVS_NSH_KEY_ATTR_NSHC4 */ +} + size_t ovs_key_attr_size(void) { /* Whenever adding new OVS_KEY_ FIELDS, we should consider * updating this function. */ - BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 26); + BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 27); return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */ + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */ @@ -300,6 +320,8 @@ size_t ovs_key_attr_size(void) + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */ + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */ + nla_total_size(4) /* OVS_KEY_ATTR_VLAN */ + + nla_total_size(0) /* OVS_KEY_ATTR_NSH */ + + ovs_nsh_key_attr_size() + nla_total_size(0) /* OVS_KEY_ATTR_ENCAP */ + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */ + nla_total_size(40) /* OVS_KEY_ATTR_IPV6 */ @@ -327,6 +349,18 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] .next = ovs_vxlan_ext_key_lens }, }; +static const struct ovs_len_tbl ovs_nsh_key_lens[OVS_NSH_KEY_ATTR_MAX + 1] = { + [OVS_NSH_KEY_ATTR_FLAGS] = { .len = 1 }, + [OVS_NSH_KEY_ATTR_MD_TYPE] = { .len = 1 }, + [OVS_NSH_KEY_ATTR_NEXT_PROTO] = { .len = 1 }, + [OVS_NSH_KEY_ATTR_NSI] = { .len = 1 }, + [OVS_NSH_KEY_ATTR_NSP] = { .len = 4 }, + [OVS_NSH_KEY_ATTR_NSHC1] = { .len = 4 }, + [OVS_NSH_KEY_ATTR_NSHC2] = { .len = 4 }, + [OVS_NSH_KEY_ATTR_NSHC3] = { .len = 4 }, + [OVS_NSH_KEY_ATTR_NSHC4] = { .len = 4 }, +}; + /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { [OVS_KEY_ATTR_ENCAP] = { .len = OVS_ATTR_NESTED }, @@ -335,6 +369,8 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { [OVS_KEY_ATTR_SKB_MARK] = { .len = sizeof(u32) }, [OVS_KEY_ATTR_ETHERNET] = { .len = sizeof(struct ovs_key_ethernet) }, [OVS_KEY_ATTR_VLAN] = { .len = sizeof(__be16) }, + [OVS_KEY_ATTR_NSH] = { .len = OVS_ATTR_NESTED, + .next = ovs_nsh_key_lens, }, [OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) }, [OVS_KEY_ATTR_IPV4] = { .len = sizeof(struct ovs_key_ipv4) }, [OVS_KEY_ATTR_IPV6] = { .len = sizeof(struct ovs_key_ipv6) }, @@ -853,6 +889,151 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, return 0; } +static int nsh_from_nlattr(const struct nlattr *attr, + struct sw_flow_match *match, bool is_mask, + bool log) +{ + struct nlattr *a; + int rem; + + nla_for_each_nested(a, attr, rem) { + int type = nla_type(a); + + if (type > OVS_NSH_KEY_ATTR_MAX) { + OVS_NLERR(log, "NSH attr %d out of range max %d", + type, OVS_NSH_KEY_ATTR_MAX); + return -EINVAL; + } + + if (!check_attr_len(nla_len(a), + ovs_nsh_key_lens[type].len)) { + OVS_NLERR(log, "NSH attr %d has unexpected len %d", + type, nla_len(a)); + return -EINVAL; + } + + switch (type) { + case OVS_NSH_KEY_ATTR_FLAGS: + SW_FLOW_KEY_PUT(match, nsh.flags, + nla_get_u8(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_MD_TYPE: + SW_FLOW_KEY_PUT(match, nsh.md_type, + nla_get_u8(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_NEXT_PROTO: + SW_FLOW_KEY_PUT(match, nsh.next_proto, + nla_get_u8(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_NSI: + SW_FLOW_KEY_PUT(match, nsh.nsi, + nla_get_u8(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_NSP: + SW_FLOW_KEY_PUT(match, nsh.nsp, + nla_get_be32(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_NSHC1: + SW_FLOW_KEY_PUT(match, nsh.nshc1, + nla_get_be32(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_NSHC2: + SW_FLOW_KEY_PUT(match, nsh.nshc2, + nla_get_be32(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_NSHC3: + SW_FLOW_KEY_PUT(match, nsh.nshc3, + nla_get_be32(a), is_mask); + break; + case OVS_NSH_KEY_ATTR_NSHC4: + SW_FLOW_KEY_PUT(match, nsh.nshc4, + nla_get_be32(a), is_mask); + break; + default: + OVS_NLERR(log, "Unknown NSH attribute %d", + type); + return -EINVAL; + } + } + + if (rem > 0) { + OVS_NLERR(log, "NSH attribute has %d unknown bytes.", + rem); + return -EINVAL; + } + + if (!is_mask) { + if (!match->key->nsh.md_type) { + OVS_NLERR(log, "NSH Header MD Type is zero"); + return -EINVAL; + } + } + + return 0; +} + +static int __nsh_to_nlattr(struct sk_buff *skb, + const struct ovs_nsh_key *output) +{ + if (output->md_type) { + if (output->flags && + nla_put_u8(skb, OVS_NSH_KEY_ATTR_FLAGS, + output->flags)) + return -EMSGSIZE; + if (nla_put_u8(skb, OVS_NSH_KEY_ATTR_MD_TYPE, + output->md_type)) + return -EMSGSIZE; + if (output->next_proto && + nla_put_u8(skb, OVS_NSH_KEY_ATTR_NEXT_PROTO, + output->next_proto)) + return -EMSGSIZE; + if (output->nsi && + nla_put_u8(skb, OVS_NSH_KEY_ATTR_NSI, + output->nsi)) + return -EMSGSIZE; + if (output->nsp && + nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSP, + output->nsp)) + return -EMSGSIZE; + if (output->nshc1 && + nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC1, + output->nshc1)) + return -EMSGSIZE; + if (output->nshc2 && + nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC2, + output->nshc2)) + return -EMSGSIZE; + if (output->nshc3 && + nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC3, + output->nshc3)) + return -EMSGSIZE; + if (output->nshc4 && + nla_put_be32(skb, OVS_NSH_KEY_ATTR_NSHC4, + output->nshc4)) + return -EMSGSIZE; + } + + return 0; +} + +static int nsh_to_nlattr(struct sk_buff *skb, + const struct ovs_nsh_key *output) +{ + struct nlattr *nla; + int err; + + nla = nla_nest_start(skb, OVS_KEY_ATTR_NSH); + if (!nla) + return -EMSGSIZE; + + err = __nsh_to_nlattr(skb, output); + if (err) + return err; + + nla_nest_end(skb, nla); + return 0; +} + static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, u64 attrs, const struct nlattr **a, bool is_mask, bool log) @@ -863,6 +1044,14 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, if (err) return err; + if (attrs & (1 << OVS_KEY_ATTR_NSH)) { + if (nsh_from_nlattr(a[OVS_KEY_ATTR_NSH], match, + is_mask, log) < 0) { + return -EINVAL; + } + attrs &= ~(1 << OVS_KEY_ATTR_NSH); + } + if (attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) { const struct ovs_key_ethernet *eth_key; @@ -1391,6 +1580,11 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey, goto nla_put_failure; } + if ((swkey->nsh.md_type)) { + if (nsh_to_nlattr(skb, &output->nsh)) + goto nla_put_failure; + } + if (swkey->phy.in_port == DP_MAX_PORTS) { if (is_mask && (output->phy.in_port == 0xffff)) if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, 0xffffffff)) diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index bd37594..6cde92a 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -341,6 +341,7 @@ enum ovs_key_attr { OVS_KEY_ATTR_ND, /* struct ovs_key_nd */ OVS_KEY_ATTR_SKB_MARK, /* u32 skb mark */ OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */ + OVS_KEY_ATTR_NSH, /* Nested set of ovs_nsh attributes */ OVS_KEY_ATTR_SCTP, /* struct ovs_key_sctp */ OVS_KEY_ATTR_TCP_FLAGS, /* be16 TCP flags. */ OVS_KEY_ATTR_DP_HASH, /* u32 hash value. Value 0 indicates the hash @@ -383,6 +384,21 @@ enum ovs_tunnel_key_attr { #define OVS_TUNNEL_KEY_ATTR_MAX (__OVS_TUNNEL_KEY_ATTR_MAX - 1) +enum ovs_nsh_key_attr { + OVS_NSH_KEY_ATTR_FLAGS, /* u8 NSH header flags */ + OVS_NSH_KEY_ATTR_MD_TYPE, /* u8 Metadata Type */ + OVS_NSH_KEY_ATTR_NEXT_PROTO, /* u8 Next Protocol */ + OVS_NSH_KEY_ATTR_NSI, /* u8 Service Index */ + OVS_NSH_KEY_ATTR_NSP, /* be32 Service Path ID */ + OVS_NSH_KEY_ATTR_NSHC1, /* be32 NSH Context Header 1 */ + OVS_NSH_KEY_ATTR_NSHC2, /* be32 NSH Context Header 2 */ + OVS_NSH_KEY_ATTR_NSHC3, /* be32 NSH Context Header 3 */ + OVS_NSH_KEY_ATTR_NSHC4, /* be32 NSH Context Header 4 */ + __OVS_NSH_KEY_ATTR_MAX +}; + +#define OVS_NSH_KEY_ATTR_MAX (__OVS_NSH_KEY_ATTR_MAX - 1) + /** * enum ovs_frag_type - IPv4 and IPv6 fragment type * @OVS_FRAG_TYPE_NONE: Packet is not a fragment. diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 4239624..2de81dc 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -336,6 +336,7 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a) case OVS_KEY_ATTR_CT_ZONE: case OVS_KEY_ATTR_CT_MARK: case OVS_KEY_ATTR_CT_LABELS: + case OVS_KEY_ATTR_NSH: /* Not support SET command for this version */ case __OVS_KEY_ATTR_MAX: default: OVS_NOT_REACHED(); @@ -435,6 +436,7 @@ odp_execute_masked_set_action(struct dp_packet *packet, case OVS_KEY_ATTR_ICMP: case OVS_KEY_ATTR_ICMPV6: case OVS_KEY_ATTR_TCP_FLAGS: + case OVS_KEY_ATTR_NSH: /* Not support SET command for this version */ case __OVS_KEY_ATTR_MAX: default: OVS_NOT_REACHED(); diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index fbc82b7..982e676 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -1036,6 +1036,7 @@ sflow_read_set_action(const struct nlattr *attr, case OVS_KEY_ATTR_CT_MARK: case OVS_KEY_ATTR_CT_LABELS: case OVS_KEY_ATTR_UNSPEC: + case OVS_KEY_ATTR_NSH: /* Not support SET command for this version */ case __OVS_KEY_ATTR_MAX: default: break; -- 1.8.4.2 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev