From 94872594b79d1a4a6cfb9434b1c1d1d506b3c57d Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Tue, 27 May 2014 21:50:35 -0700 Subject: [PATCH] tunnel: Add support for matching on OAM packets. Some tunnel formats have mechanisms for indicating that packets are OAM frames that should be handled specially (either as high priority or not forwarded beyond an endpoint). This provides support for allowing those types of packets to be matched. Signed-off-by: Jesse Gross Acked-by: Thomas Graf Acked-by: Pravin B Shelar --- datapath/datapath.c | 1 + datapath/flow_netlink.c | 7 +++++++ datapath/linux/compat/include/net/ip_tunnels.h | 4 ++++ include/linux/openvswitch.h | 1 + lib/flow.c | 2 ++ lib/flow.h | 1 + lib/odp-util.c | 10 +++++++++- lib/odp-util.h | 3 ++- 8 files changed, 27 insertions(+), 2 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 351a0756361..32a46836d2e 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -393,6 +393,7 @@ static size_t key_attr_size(void) + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */ + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */ + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */ + + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */ + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */ + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */ + nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */ diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index 0048a6e90ec..c5ca2f49012 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -347,6 +347,7 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr, [OVS_TUNNEL_KEY_ATTR_TTL] = 1, [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0, [OVS_TUNNEL_KEY_ATTR_CSUM] = 0, + [OVS_TUNNEL_KEY_ATTR_OAM] = 0, }; if (type > OVS_TUNNEL_KEY_ATTR_MAX) { @@ -391,6 +392,9 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr, case OVS_TUNNEL_KEY_ATTR_CSUM: tun_flags |= TUNNEL_CSUM; break; + case OVS_TUNNEL_KEY_ATTR_OAM: + tun_flags |= TUNNEL_OAM; + break; default: return -EINVAL; } @@ -448,6 +452,9 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb, if ((output->tun_flags & TUNNEL_CSUM) && nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM)) return -EMSGSIZE; + if ((output->tun_flags & TUNNEL_OAM) && + nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM)) + return -EMSGSIZE; nla_nest_end(skb, nla); return 0; diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index e59f9f3563b..e2f3c30f4d3 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -44,4 +44,8 @@ int iptunnel_xmit(struct rtable *rt, int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto); #endif + +/* Not yet upstream */ +#define TUNNEL_OAM __cpu_to_be16(0x0200) + #endif /* __NET_IP_TUNNELS_H */ diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index 33423add108..57d40e38372 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -340,6 +340,7 @@ enum ovs_tunnel_key_attr { OVS_TUNNEL_KEY_ATTR_TTL, /* u8 Tunnel IP TTL. */ OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT, /* No argument, set DF. */ OVS_TUNNEL_KEY_ATTR_CSUM, /* No argument. CSUM packet. */ + OVS_TUNNEL_KEY_ATTR_OAM, /* No argument, OAM frame. */ __OVS_TUNNEL_KEY_ATTR_MAX }; diff --git a/lib/flow.c b/lib/flow.c index 1f7f3100a9c..88c6ef122ef 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -687,6 +687,8 @@ flow_tun_flag_to_string(uint32_t flags) return "csum"; case FLOW_TNL_F_KEY: return "key"; + case FLOW_TNL_F_OAM: + return "oam"; default: return NULL; } diff --git a/lib/flow.h b/lib/flow.h index 139e7f68b55..76750843b18 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -58,6 +58,7 @@ BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER); #define FLOW_TNL_F_DONT_FRAGMENT (1 << 0) #define FLOW_TNL_F_CSUM (1 << 1) #define FLOW_TNL_F_KEY (1 << 2) +#define FLOW_TNL_F_OAM (1 << 3) const char *flow_tun_flag_to_string(uint32_t flags); diff --git a/lib/odp-util.c b/lib/odp-util.c index 3c69adaf41a..8f71c7c8fc9 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -832,6 +832,7 @@ tunnel_key_attr_len(int type) case OVS_TUNNEL_KEY_ATTR_TTL: return 1; case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT: return 0; case OVS_TUNNEL_KEY_ATTR_CSUM: return 0; + case OVS_TUNNEL_KEY_ATTR_OAM: return 0; case __OVS_TUNNEL_KEY_ATTR_MAX: return -1; } @@ -879,6 +880,9 @@ odp_tun_key_from_attr(const struct nlattr *attr, struct flow_tnl *tun) case OVS_TUNNEL_KEY_ATTR_CSUM: tun->flags |= FLOW_TNL_F_CSUM; break; + case OVS_TUNNEL_KEY_ATTR_OAM: + tun->flags |= FLOW_TNL_F_OAM; + break; default: /* Allow this to show up as unexpected, if there are unknown * tunnel attribute, eventually resulting in ODP_FIT_TOO_MUCH. */ @@ -923,6 +927,9 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key) if (tun_key->flags & FLOW_TNL_F_CSUM) { nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_CSUM); } + if (tun_key->flags & FLOW_TNL_F_OAM) { + nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_OAM); + } nl_msg_end_nested(a, tun_key_ofs); } @@ -949,7 +956,8 @@ odp_mask_attr_is_exact(const struct nlattr *ma) odp_tun_key_from_attr(ma, &tun_mask); if (tun_mask.flags == (FLOW_TNL_F_KEY | FLOW_TNL_F_DONT_FRAGMENT - | FLOW_TNL_F_CSUM)) { + | FLOW_TNL_F_CSUM + | FLOW_TNL_F_OAM)) { /* The flags are exact match, check the remaining fields. */ tun_mask.flags = 0xffff; is_exact = is_all_ones((uint8_t *)&tun_mask, diff --git a/lib/odp-util.h b/lib/odp-util.h index aad3098cdc9..0e912a4ada0 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -104,6 +104,7 @@ void odp_portno_names_destroy(struct hmap *portno_names); * - OVS_TUNNEL_KEY_ATTR_TTL 1 3 4 8 * - OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT 0 -- 4 4 * - OVS_TUNNEL_KEY_ATTR_CSUM 0 -- 4 4 + * - OVS_TUNNEL_KEY_ATTR_OAM 0 -- 4 4 * OVS_KEY_ATTR_IN_PORT 4 -- 4 8 * OVS_KEY_ATTR_SKB_MARK 4 -- 4 8 * OVS_KEY_ATTR_DP_HASH 4 -- 4 8 @@ -117,7 +118,7 @@ void odp_portno_names_destroy(struct hmap *portno_names); * OVS_KEY_ATTR_ICMPV6 2 2 4 8 * OVS_KEY_ATTR_ND 28 -- 4 32 * ---------------------------------------------------------- - * total 224 + * total 228 * * We include some slack space in case the calculation isn't quite right or we * add another field and forget to adjust this value.