Re: [PATCH net-next 5/5] vxlan: implement GPE in L3 mode

2016-03-08 Thread Jesse Gross
On Sat, Feb 27, 2016 at 11:44 AM, Jiri Benc  wrote:
> On Sat, 27 Feb 2016 20:21:59 +0100, Jiri Benc wrote:
>> You mean returning ETH_P_TEB in skb->protocol? That's not much useful,
>> unfortunately. You won't get such packet processed by the kernel IP
>> stack, rendering the VXLAN-GPE device unusable outside of ovs. It would
>> effectively became a packet sink when used standalone, as it cannot be
>> added to bridge and received packets are not processed by anything -
>> there's no protocol handler for ETH_P_TEB.
>
> Actually, I can do that in the L3 mode (or whatever we'll call it). It
> won't hurt anything and may be useful for openvswitch. Ovs will have to
> special case VXLAN-GPE vport (or perhaps any ARPHRD_NONE port) and set
> skb->protocol to ETH_P_TEB on xmit and dissect correctly the ETH_P_TEB
> packet on rcv.
>
> The L2 mode (or whatever we'll call it) will need to stay, though, for
> non-ovs use cases.

Sorry for the delay in responding but this plan sounds good to me.


Re: [PATCH net-next 5/5] vxlan: implement GPE in L3 mode

2016-02-27 Thread Jiri Benc
On Sat, 27 Feb 2016 20:21:59 +0100, Jiri Benc wrote:
> You mean returning ETH_P_TEB in skb->protocol? That's not much useful,
> unfortunately. You won't get such packet processed by the kernel IP
> stack, rendering the VXLAN-GPE device unusable outside of ovs. It would
> effectively became a packet sink when used standalone, as it cannot be
> added to bridge and received packets are not processed by anything -
> there's no protocol handler for ETH_P_TEB.

Actually, I can do that in the L3 mode (or whatever we'll call it). It
won't hurt anything and may be useful for openvswitch. Ovs will have to
special case VXLAN-GPE vport (or perhaps any ARPHRD_NONE port) and set
skb->protocol to ETH_P_TEB on xmit and dissect correctly the ETH_P_TEB
packet on rcv.

The L2 mode (or whatever we'll call it) will need to stay, though, for
non-ovs use cases.

 Jiri


Re: [PATCH net-next 5/5] vxlan: implement GPE in L3 mode

2016-02-27 Thread Jiri Benc
On Fri, 26 Feb 2016 15:42:29 -0800, Tom Herbert wrote:
> Agreed, and I don't see why there even needs to be modes. VXLAN-GPE
> can carry arbitrary protocols with a next-header field. For Ethernet,
> MPLS, IPv4, and IPv6 it should just be a simple mapping of the next
> header to Ethertype for purposes of processing the payload.

That's exactly what this patchset does, Tom. The mapping is done in
vxlan_parse_gpe_hdr and vxlan_build_gpe_hdr.

Ethernet is special, though. It needs to be a standalone mode,
otherwise frames encapsulated including an Ethernet header wouldn't be
processed and there would be no way to send such packets - the only
distinction the driver can use is skb->protocol and that won't become
ETH_P_TEB magically.

 Jiri


Re: [PATCH net-next 5/5] vxlan: implement GPE in L3 mode

2016-02-27 Thread Jiri Benc
On Fri, 26 Feb 2016 14:22:03 -0800, Jesse Gross wrote:
> Given that VXLAN_GPE_MODE_L3 will eventually come to be used by NSH,
> MPLS, etc. in addition to IPv4/v6, most of which are not really L3, it
> seems like something along the lines of NO_ARP might be better since
> that's what it really indicates.

I have no problem naming this differently. Not sure NO_ARP is the best
name, though - this is more about absence of the L2 header in received
packets than about ARP.

> Once that is in, I don't really see
> the need to explicitly block Ethernet packets from being handled in
> this mode. If they are received, then they can just be handed off to
> the stack - at that point it would look like an extra header, the same
> as if an NSH packet is received.

You mean returning ETH_P_TEB in skb->protocol? That's not much useful,
unfortunately. You won't get such packet processed by the kernel IP
stack, rendering the VXLAN-GPE device unusable outside of ovs. It would
effectively became a packet sink when used standalone, as it cannot be
added to bridge and received packets are not processed by anything -
there's no protocol handler for ETH_P_TEB.

With this patchset, you can create a VXLAN-GPE interface and use it as
any other point to point interface, and it works as expected with
routing etc.

The distinction between Ethernet and no Ethernet is needed, the
interface won't work otherwise.

 Jiri


Re: [PATCH net-next 5/5] vxlan: implement GPE in L3 mode

2016-02-26 Thread Tom Herbert
On Fri, Feb 26, 2016 at 2:22 PM, Jesse Gross  wrote:
> On Thu, Feb 25, 2016 at 11:48 PM, Jiri Benc  wrote:
>> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
>> index c2b2b7462731..ee4f7198aa21 100644
>> --- a/include/uapi/linux/if_link.h
>> +++ b/include/uapi/linux/if_link.h
>> @@ -464,6 +464,7 @@ enum {
>>  enum vxlan_gpe_mode {
>> VXLAN_GPE_MODE_DISABLED = 0,
>> VXLAN_GPE_MODE_L2,
>> +   VXLAN_GPE_MODE_L3,
>
> Given that VXLAN_GPE_MODE_L3 will eventually come to be used by NSH,
> MPLS, etc. in addition to IPv4/v6, most of which are not really L3, it
> seems like something along the lines of NO_ARP might be better since
> that's what it really indicates. Once that is in, I don't really see
> the need to explicitly block Ethernet packets from being handled in
> this mode. If they are received, then they can just be handed off to
> the stack - at that point it would look like an extra header, the same
> as if an NSH packet is received.

Agreed, and I don't see why there even needs to be modes. VXLAN-GPE
can carry arbitrary protocols with a next-header field. For Ethernet,
MPLS, IPv4, and IPv6 it should just be a simple mapping of the next
header to Ethertype for purposes of processing the payload.


Re: [PATCH net-next 5/5] vxlan: implement GPE in L3 mode

2016-02-26 Thread Jesse Gross
On Thu, Feb 25, 2016 at 11:48 PM, Jiri Benc  wrote:
> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> index c2b2b7462731..ee4f7198aa21 100644
> --- a/include/uapi/linux/if_link.h
> +++ b/include/uapi/linux/if_link.h
> @@ -464,6 +464,7 @@ enum {
>  enum vxlan_gpe_mode {
> VXLAN_GPE_MODE_DISABLED = 0,
> VXLAN_GPE_MODE_L2,
> +   VXLAN_GPE_MODE_L3,

Given that VXLAN_GPE_MODE_L3 will eventually come to be used by NSH,
MPLS, etc. in addition to IPv4/v6, most of which are not really L3, it
seems like something along the lines of NO_ARP might be better since
that's what it really indicates. Once that is in, I don't really see
the need to explicitly block Ethernet packets from being handled in
this mode. If they are received, then they can just be handed off to
the stack - at that point it would look like an extra header, the same
as if an NSH packet is received.


[PATCH net-next 5/5] vxlan: implement GPE in L3 mode

2016-02-25 Thread Jiri Benc
Implement L3 mode for VXLAN-GPE (i.e. IPv4/IPv6 payload directly after the
VXLAN header).

The GPE header parsing has to be moved before iptunnel_pull_header, as we
need to know the protocol.

Signed-off-by: Jiri Benc 
---
 drivers/net/vxlan.c  | 127 +++
 include/net/vxlan.h  |   3 +-
 include/uapi/linux/if_link.h |   1 +
 3 files changed, 108 insertions(+), 23 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 81a7c1a829b9..b79472d3fd36 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1191,6 +1191,7 @@ out:
 }
 
 static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed,
+   __be32 *protocol,
struct sk_buff *skb, u32 vxflags)
 {
struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed;
@@ -1210,9 +1211,30 @@ static bool vxlan_parse_gpe_hdr(struct vxlanhdr 
*unparsed,
if (gpe->oam_flag)
return false;
 
-   if (gpe->next_protocol != VXLAN_GPE_NP_ETHERNET)
+   /* L2 mode */
+   if (gpe->next_protocol == VXLAN_GPE_NP_ETHERNET) {
+   if (vxflags & VXLAN_F_GPE_L3)
+   return false;
+   *protocol = htons(ETH_P_TEB);
+   goto out;
+   }
+
+   /* L3 mode */
+   if (!(vxflags & VXLAN_F_GPE_L3))
+   return false;
+
+   switch (gpe->next_protocol) {
+   case VXLAN_GPE_NP_IPV4:
+   *protocol = htons(ETH_P_IP);
+   break;
+   case VXLAN_GPE_NP_IPV6:
+   *protocol = htons(ETH_P_IPV6);
+   break;
+   default:
return false;
+   }
 
+out:
unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS;
return true;
 }
@@ -1282,9 +1304,10 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff 
*skb)
struct vxlanhdr unparsed;
struct vxlan_metadata _md;
struct vxlan_metadata *md = &_md;
+   __be32 protocol = htons(ETH_P_TEB);
void *oiph;
 
-   /* Need Vxlan and inner Ethernet header to be present */
+   /* Need UDP and VXLAN header to be present */
if (!pskb_may_pull(skb, VXLAN_HLEN))
return 1;
 
@@ -1308,7 +1331,14 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff 
*skb)
if (!vxlan)
goto drop;
 
-   if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB),
+   /* For backwards compatibility, only allow reserved fields to be
+* used by VXLAN extensions if explicitly requested.
+*/
+   if (vs->flags & VXLAN_F_GPE)
+   if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
+   goto drop;
+
+   if (iptunnel_pull_header(skb, VXLAN_HLEN, protocol,
 !net_eq(vxlan->net, dev_net(vxlan->dev
goto drop;
 
@@ -1329,12 +1359,6 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff 
*skb)
memset(md, 0, sizeof(*md));
}
 
-   /* For backwards compatibility, only allow reserved fields to be
-* used by VXLAN extensions if explicitly requested.
-*/
-   if (vs->flags & VXLAN_F_GPE)
-   if (!vxlan_parse_gpe_hdr(&unparsed, skb, vs->flags))
-   goto drop;
if (vs->flags & VXLAN_F_REMCSUM_RX)
if (!vxlan_remcsum(&unparsed, skb, vs->flags))
goto drop;
@@ -1353,8 +1377,13 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff 
*skb)
goto drop;
}
 
-   if (!vxlan_set_mac(vxlan, vs, skb))
-   goto drop;
+   if (protocol == htons(ETH_P_TEB)) {
+   if (!vxlan_set_mac(vxlan, vs, skb))
+   goto drop;
+   } else {
+   skb->dev = vxlan->dev;
+   skb->pkt_type = PACKET_HOST;
+   }
 
oiph = skb_network_header(skb);
skb_reset_network_header(skb);
@@ -1713,12 +1742,29 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, 
u32 vxflags,
gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK);
 }
 
-static void vxlan_build_gpe_hdr(struct vxlanhdr *vxh, u32 vxflags)
+static int vxlan_build_gpe_hdr(struct vxlanhdr *vxh, u32 vxflags,
+  __be16 protocol)
 {
struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vxh;
 
gpe->np_applied = 1;
-   gpe->next_protocol = VXLAN_GPE_NP_ETHERNET;
+
+   /* L2 mode */
+   if (!(vxflags & VXLAN_F_GPE_L3)) {
+   gpe->next_protocol = VXLAN_GPE_NP_ETHERNET;
+   return 0;
+   }
+
+   /* L3 mode */
+   switch (protocol) {
+   case htons(ETH_P_IP):
+   gpe->next_protocol = VXLAN_GPE_NP_IPV4;
+   return 0;
+   case htons(ETH_P_IPV6):
+   gpe->next_protocol = VXLAN_GPE_NP_IPV6;
+   return 0;
+   }
+   return -EPFNOSUPPORT;
 }
 
 static int vxlan_build_skb(struct sk_