/* Called with rcu_read_lock and BH disabled. */
static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
{
+ struct lisp_dev *lisp_dev;
struct net_device *dev;
struct lisphdr *lisph;
struct iphdr *inner_iph;
struct metadata_dst *tun_dst;
-#ifndef HAVE_METADATA_DST
+#ifndef USE_UPSTREAM_TUNNEL
struct metadata_dst temp;
#endif
__be64 key;
if (unlikely(!dev))
goto error;
- if (iptunnel_pull_header(skb, LISP_HLEN, 0))
+ lisp_dev = netdev_priv(dev);
+ if (iptunnel_pull_header(skb, LISP_HLEN, 0,
+ !net_eq(lisp_dev->net, dev_net(lisp_dev->dev))))
goto error;
lisph = lisp_hdr(skb);
key = instance_id_to_tunnel_id(&lisph->u2.word2.instance_id[0]);
/* Save outer tunnel values */
-#ifndef HAVE_METADATA_DST
+#ifndef USE_UPSTREAM_TUNNEL
tun_dst = &temp;
- ovs_udp_tun_rx_dst(&tun_dst->u.tun_info, skb, AF_INET, TUNNEL_KEY, key, 0);
+ ovs_udp_tun_rx_dst(tun_dst, skb, AF_INET, TUNNEL_KEY, key, 0);
#else
tun_dst = udp_tun_rx_dst(skb, AF_INET, TUNNEL_KEY, key, 0);
#endif
return 0;
}
+static struct rtable *lisp_get_rt(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi4 *fl,
+ const struct ip_tunnel_key *key)
+{
+ struct net *net = dev_net(dev);
+
+ /* Route lookup */
+ memset(fl, 0, sizeof(*fl));
+ fl->daddr = key->u.ipv4.dst;
+ fl->saddr = key->u.ipv4.src;
+ fl->flowi4_tos = RT_TOS(key->tos);
+ fl->flowi4_mark = skb->mark;
+ fl->flowi4_proto = IPPROTO_UDP;
+
+ return ip_route_output_key(net, fl);
+}
+
netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
tun_key = &info->key;
- /* Route lookup */
- memset(&fl, 0, sizeof(fl));
- fl.daddr = tun_key->u.ipv4.dst;
- fl.saddr = tun_key->u.ipv4.src;
- fl.flowi4_tos = RT_TOS(tun_key->tos);
- fl.flowi4_mark = skb->mark;
- fl.flowi4_proto = IPPROTO_UDP;
- rt = ip_route_output_key(net, &fl);
+ rt = lisp_get_rt(skb, dev, &fl, tun_key);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
goto error;
skb_reset_mac_header(skb);
skb->vlan_tci = 0;
- skb = udp_tunnel_handle_offloads(skb, false, 0, false);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- skb = NULL;
+ err = udp_tunnel_handle_offloads(skb, false, false);
+ if (err)
goto err_free_rt;
- }
src_port = htons(get_src_port(net, skb));
dst_port = lisp_dev->dst_port;
ovs_skb_set_inner_protocol(skb, skb->protocol);
df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
- err = udp_tunnel_xmit_skb(rt, lisp_dev->sock->sk, skb,
- fl.saddr, tun_key->u.ipv4.dst,
- tun_key->tos, tun_key->ttl,
- df, src_port, dst_port, false, true);
+ udp_tunnel_xmit_skb(rt, lisp_dev->sock->sk, skb,
+ fl.saddr, tun_key->u.ipv4.dst,
+ tun_key->tos, tun_key->ttl,
+ df, src_port, dst_port, false, true);
- iptunnel_xmit_stats(err, &dev->stats, (struct pcpu_sw_netstats __percpu *)dev->tstats);
return NETDEV_TX_OK;
err_free_rt:
static netdev_tx_t lisp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
-#ifdef HAVE_METADATA_DST
+#ifdef USE_UPSTREAM_TUNNEL
return rpl_lisp_xmit(skb);
#else
/* Drop All packets coming from networking stack. OVS-CB is
return 0;
}
+static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
+ struct ip_tunnel_info *info,
+ __be16 sport, __be16 dport)
+{
+ struct rtable *rt;
+ struct flowi4 fl4;
+
+ rt = lisp_get_rt(skb, dev, &fl4, &info->key);
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
+ ip_rt_put(rt);
+
+ info->key.u.ipv4.src = fl4.saddr;
+ info->key.tp_src = sport;
+ info->key.tp_dst = dport;
+ return 0;
+}
+
+int ovs_lisp_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+ struct lisp_dev *lisp = netdev_priv(dev);
+ struct net *net = lisp->net;
+ struct ip_tunnel_info *info = skb_tunnel_info(skb);
+ __be16 sport, dport;
+
+ sport = htons(get_src_port(net, skb));
+ dport = lisp->dst_port;
+
+ if (ip_tunnel_info_af(info) == AF_INET)
+ return egress_ipv4_tun_info(dev, skb, info, sport, dport);
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(ovs_lisp_fill_metadata_dst);
+
static const struct net_device_ops lisp_netdev_ops = {
.ndo_init = lisp_init,
.ndo_uninit = lisp_uninit,
.ndo_change_mtu = lisp_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
+#ifdef USE_UPSTREAM_TUNNEL
+#ifdef HAVE_NDO_FILL_METADATA_DST
+ .ndo_fill_metadata_dst = lisp_fill_metadata_dst,
+#endif
+#endif
};
static void lisp_get_drvinfo(struct net_device *dev,
dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
#endif
-#ifdef HAVE_METADATA_DST
+#ifdef USE_UPSTREAM_TUNNEL
netif_keep_dst(dev);
#endif
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;