Re: [PATCH net-next v12 6/9] openvswitch: netlink: support L3 packets

2016-10-20 Thread Pravin Shelar
On Mon, Oct 17, 2016 at 6:02 AM, Jiri Benc  wrote:
> Extend the ovs flow netlink protocol to support L3 packets. Packets without
> OVS_KEY_ATTR_ETHERNET attribute specify L3 packets; for those, the
> OVS_KEY_ATTR_ETHERTYPE attribute is mandatory.
>
> Push/pop vlan actions are only supported for Ethernet packets.
>
> Based on previous versions by Lorand Jakab and Simon Horman.
>
> Signed-off-by: Lorand Jakab 
> Signed-off-by: Simon Horman 
> Signed-off-by: Jiri Benc 

Acked-by: Pravin B Shelar 


[PATCH net-next v12 6/9] openvswitch: netlink: support L3 packets

2016-10-17 Thread Jiri Benc
Extend the ovs flow netlink protocol to support L3 packets. Packets without
OVS_KEY_ATTR_ETHERNET attribute specify L3 packets; for those, the
OVS_KEY_ATTR_ETHERTYPE attribute is mandatory.

Push/pop vlan actions are only supported for Ethernet packets.

Based on previous versions by Lorand Jakab and Simon Horman.

Signed-off-by: Lorand Jakab 
Signed-off-by: Simon Horman 
Signed-off-by: Jiri Benc 
---
 net/openvswitch/flow_netlink.c | 160 +
 1 file changed, 99 insertions(+), 61 deletions(-)

diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index ccb9900c5230..c3d0cc4321c3 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -123,7 +123,7 @@ static void update_range(struct sw_flow_match *match,
 static bool match_validate(const struct sw_flow_match *match,
   u64 key_attrs, u64 mask_attrs, bool log)
 {
-   u64 key_expected = 1 << OVS_KEY_ATTR_ETHERNET;
+   u64 key_expected = 0;
u64 mask_allowed = key_attrs;  /* At most allow all key attributes */
 
/* The following mask attributes allowed only if they
@@ -969,10 +969,33 @@ static int parse_vlan_from_nlattrs(struct sw_flow_match 
*match,
return 0;
 }
 
+static int parse_eth_type_from_nlattrs(struct sw_flow_match *match,
+  u64 *attrs, const struct nlattr **a,
+  bool is_mask, bool log)
+{
+   __be16 eth_type;
+
+   eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
+   if (is_mask) {
+   /* Always exact match EtherType. */
+   eth_type = htons(0x);
+   } else if (!eth_proto_is_802_3(eth_type)) {
+   OVS_NLERR(log, "EtherType %x is less than min %x",
+   ntohs(eth_type), ETH_P_802_3_MIN);
+   return -EINVAL;
+   }
+
+   SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
+   *attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
+   return 0;
+}
+
 static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
 u64 *attrs, const struct nlattr **a,
 bool is_mask, bool log)
 {
+   u8 mac_proto = MAC_PROTO_ETHERNET;
+
if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
 
@@ -1060,9 +1083,19 @@ static int metadata_from_nlattrs(struct net *net, struct 
sw_flow_match *match,
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
}
 
+   /* For layer 3 packets the Ethernet type is provided
+* and treated as metadata but no MAC addresses are provided.
+*/
+   if (!(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) &&
+   (*attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE)))
+   mac_proto = MAC_PROTO_NONE;
+
/* Always exact match mac_proto */
-   SW_FLOW_KEY_PUT(match, mac_proto, is_mask ? 0xff : MAC_PROTO_ETHERNET,
-   is_mask);
+   SW_FLOW_KEY_PUT(match, mac_proto, is_mask ? 0xff : mac_proto, is_mask);
+
+   if (mac_proto == MAC_PROTO_NONE)
+   return parse_eth_type_from_nlattrs(match, attrs, a, is_mask,
+  log);
 
return 0;
 }
@@ -1086,33 +1119,26 @@ static int ovs_key_from_nlattrs(struct net *net, struct 
sw_flow_match *match,
SW_FLOW_KEY_MEMCPY(match, eth.dst,
eth_key->eth_dst, ETH_ALEN, is_mask);
attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
-   }
-
-   if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
-   /* VLAN attribute is always parsed before getting here since it
-* may occur multiple times.
-*/
-   OVS_NLERR(log, "VLAN attribute unexpected.");
-   return -EINVAL;
-   }
-
-   if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
-   __be16 eth_type;
 
-   eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
-   if (is_mask) {
-   /* Always exact match EtherType. */
-   eth_type = htons(0x);
-   } else if (!eth_proto_is_802_3(eth_type)) {
-   OVS_NLERR(log, "EtherType %x is less than min %x",
- ntohs(eth_type), ETH_P_802_3_MIN);
+   if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
+   /* VLAN attribute is always parsed before getting here 
since it
+* may occur multiple times.
+*/
+   OVS_NLERR(log, "VLAN attribute unexpected.");
return -EINVAL;
}
 
-   SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
-   attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
-   }