Commit b8223bd1 authored by David S. Miller's avatar David S. Miller

Merge branch 'gre-teb'

Jiri Benc says:

====================
gre: receive also TEB packets for lwtunnels

NOTE: this patchset needs net merged to net-next.

This allows lwtunnel users to get also packets with ETH_P_TEB protocol
specified in GRE header through an ipgre interface. There's really nothing
special about these packets in the case of lwtunnels - it's just an inner
protocol like any other. The only complications stem from keeping
compatibility with other uses of GRE.

This will be used by openvswitch to support eth_push and eth_pop actions.
I'd also like to see tc support for lwtunnels (this feature included) in the
future.

The first patch is not directly related and can be submitted standalone if
needed.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3f7496aa 125372fa
...@@ -160,6 +160,7 @@ struct tnl_ptk_info { ...@@ -160,6 +160,7 @@ struct tnl_ptk_info {
#define PACKET_RCVD 0 #define PACKET_RCVD 0
#define PACKET_REJECT 1 #define PACKET_REJECT 1
#define PACKET_NEXT 2
#define IP_TNL_HASH_BITS 7 #define IP_TNL_HASH_BITS 7
#define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS) #define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS)
......
...@@ -114,11 +114,8 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, ...@@ -114,11 +114,8 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
*/ */
if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) {
tpi->proto = htons(ETH_P_IP); tpi->proto = htons(ETH_P_IP);
if ((*(u8 *)options & 0xF0) != 0x40) { if ((*(u8 *)options & 0xF0) != 0x40)
hdr_len += 4; hdr_len += 4;
if (!pskb_may_pull(skb, hdr_len))
return -EINVAL;
}
} }
return hdr_len; return hdr_len;
} }
......
...@@ -260,24 +260,22 @@ static __be32 tunnel_id_to_key(__be64 x) ...@@ -260,24 +260,22 @@ static __be32 tunnel_id_to_key(__be64 x)
#endif #endif
} }
static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
{ {
struct net *net = dev_net(skb->dev);
struct metadata_dst *tun_dst = NULL; struct metadata_dst *tun_dst = NULL;
struct ip_tunnel_net *itn;
const struct iphdr *iph; const struct iphdr *iph;
struct ip_tunnel *tunnel; struct ip_tunnel *tunnel;
if (tpi->proto == htons(ETH_P_TEB))
itn = net_generic(net, gre_tap_net_id);
else
itn = net_generic(net, ipgre_net_id);
iph = ip_hdr(skb); iph = ip_hdr(skb);
tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
iph->saddr, iph->daddr, tpi->key); iph->saddr, iph->daddr, tpi->key);
if (tunnel) { if (tunnel) {
if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
raw_proto, false) < 0)
goto drop;
skb_pop_mac_header(skb); skb_pop_mac_header(skb);
if (tunnel->collect_md) { if (tunnel->collect_md) {
__be16 flags; __be16 flags;
...@@ -293,7 +291,34 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) ...@@ -293,7 +291,34 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
return PACKET_RCVD; return PACKET_RCVD;
} }
return PACKET_REJECT; return PACKET_NEXT;
drop:
kfree_skb(skb);
return PACKET_RCVD;
}
static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
int hdr_len)
{
struct net *net = dev_net(skb->dev);
struct ip_tunnel_net *itn;
int res;
if (tpi->proto == htons(ETH_P_TEB))
itn = net_generic(net, gre_tap_net_id);
else
itn = net_generic(net, ipgre_net_id);
res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
/* ipgre tunnels in collect metadata mode should receive
* also ETH_P_TEB traffic.
*/
itn = net_generic(net, ipgre_net_id);
res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
}
return res;
} }
static int gre_rcv(struct sk_buff *skb) static int gre_rcv(struct sk_buff *skb)
...@@ -314,10 +339,7 @@ static int gre_rcv(struct sk_buff *skb) ...@@ -314,10 +339,7 @@ static int gre_rcv(struct sk_buff *skb)
if (hdr_len < 0) if (hdr_len < 0)
goto drop; goto drop;
if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
goto drop;
if (ipgre_rcv(skb, &tpi) == PACKET_RCVD)
return 0; return 0;
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment