Skip to content

Commit

Permalink
vti4: Support inter address family tunneling.
Browse files Browse the repository at this point in the history
With this patch we can tunnel ipv6 traffic via a vti4
interface. A vti4 interface can now have an ipv6 address
and ipv6 traffic can be routed via a vti4 interface.
The resulting traffic is xfrm transformed and tunneled
throuhg ipv4 if matching IPsec policies and states are
present.

Signed-off-by: Steffen Klassert <[email protected]>
  • Loading branch information
klassert committed Feb 25, 2014
1 parent a34cd4f commit 78a010c
Showing 1 changed file with 34 additions and 14 deletions.
48 changes: 34 additions & 14 deletions net/ipv4/ip_vti.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/netfilter_ipv4.h>
#include <linux/if_ether.h>
#include <linux/icmpv6.h>

#include <net/sock.h>
#include <net/ip.h>
Expand Down Expand Up @@ -122,31 +123,21 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
return 0;
}

/* This function assumes it is being called from dev_queue_xmit()
* and that skb is filled properly by that function.
*/
static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
struct flowi *fl)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
struct dst_entry *dst = skb_dst(skb);
struct net_device *tdev; /* Device to other host */
struct flowi fl;
int err;

if (skb->protocol != htons(ETH_P_IP))
goto tx_error;

memset(&fl, 0, sizeof(fl));
skb->mark = be32_to_cpu(tunnel->parms.o_key);
xfrm_decode_session(skb, &fl, AF_INET);

if (!dst) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
}

dst_hold(dst);
dst = xfrm_lookup(tunnel->net, dst, &fl, NULL, 0);
dst = xfrm_lookup(tunnel->net, dst, fl, NULL, 0);
if (IS_ERR(dst)) {
dev->stats.tx_carrier_errors++;
goto tx_error_icmp;
Expand Down Expand Up @@ -178,7 +169,6 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
tunnel->err_count = 0;
}

memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
skb_dst_set(skb, dst);
skb->dev = skb_dst(skb)->dev;
Expand All @@ -197,6 +187,36 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}

/* This function assumes it is being called from dev_queue_xmit()
* and that skb is filled properly by that function.
*/
static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
struct flowi fl;

memset(&fl, 0, sizeof(fl));

skb->mark = be32_to_cpu(tunnel->parms.o_key);

switch (skb->protocol) {
case htons(ETH_P_IP):
xfrm_decode_session(skb, &fl, AF_INET);
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
break;
case htons(ETH_P_IPV6):
xfrm_decode_session(skb, &fl, AF_INET6);
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
break;
default:
dev->stats.tx_errors++;
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}

return vti_xmit(skb, dev, &fl);
}

static int vti4_err(struct sk_buff *skb, u32 info)
{
__be32 spi;
Expand Down

0 comments on commit 78a010c

Please sign in to comment.