Commit c3ef5aa5 authored by pravin shelar's avatar pravin shelar Committed by David S. Miller

geneve: Merge ipv4 and ipv6 geneve_build_skb()

There are minimal difference in building Geneve header
between ipv4 and ipv6 geneve tunnels. Following patch
refactors code to unify it.
Signed-off-by: default avatarPravin B Shelar <pshelar@ovn.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9b4437a5
...@@ -630,67 +630,34 @@ static int geneve_stop(struct net_device *dev) ...@@ -630,67 +630,34 @@ static int geneve_stop(struct net_device *dev)
} }
static void geneve_build_header(struct genevehdr *geneveh, static void geneve_build_header(struct genevehdr *geneveh,
__be16 tun_flags, u8 vni[3], const struct ip_tunnel_info *info)
u8 options_len, u8 *options)
{ {
geneveh->ver = GENEVE_VER; geneveh->ver = GENEVE_VER;
geneveh->opt_len = options_len / 4; geneveh->opt_len = info->options_len / 4;
geneveh->oam = !!(tun_flags & TUNNEL_OAM); geneveh->oam = !!(info->key.tun_flags & TUNNEL_OAM);
geneveh->critical = !!(tun_flags & TUNNEL_CRIT_OPT); geneveh->critical = !!(info->key.tun_flags & TUNNEL_CRIT_OPT);
geneveh->rsvd1 = 0; geneveh->rsvd1 = 0;
memcpy(geneveh->vni, vni, 3); tunnel_id_to_vni(info->key.tun_id, geneveh->vni);
geneveh->proto_type = htons(ETH_P_TEB); geneveh->proto_type = htons(ETH_P_TEB);
geneveh->rsvd2 = 0; geneveh->rsvd2 = 0;
memcpy(geneveh->options, options, options_len); ip_tunnel_info_opts_get(geneveh->options, info);
} }
static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
__be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt, const struct ip_tunnel_info *info,
bool xnet) bool xnet, int ip_hdr_len)
{
bool udp_sum = !!(tun_flags & TUNNEL_CSUM);
struct genevehdr *gnvh;
int min_headroom;
int err;
skb_scrub_packet(skb, xnet);
min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
err = skb_cow_head(skb, min_headroom);
if (unlikely(err))
goto free_rt;
err = udp_tunnel_handle_offloads(skb, udp_sum);
if (err)
goto free_rt;
gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
geneve_build_header(gnvh, tun_flags, vni, opt_len, opt);
skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return 0;
free_rt:
ip_rt_put(rt);
return err;
}
#if IS_ENABLED(CONFIG_IPV6)
static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
__be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
bool xnet)
{ {
bool udp_sum = !!(tun_flags & TUNNEL_CSUM); bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
struct genevehdr *gnvh; struct genevehdr *gnvh;
int min_headroom; int min_headroom;
int err; int err;
skb_reset_mac_header(skb);
skb_scrub_packet(skb, xnet); skb_scrub_packet(skb, xnet);
min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len +
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr); GENEVE_BASE_HLEN + info->options_len + ip_hdr_len;
err = skb_cow_head(skb, min_headroom); err = skb_cow_head(skb, min_headroom);
if (unlikely(err)) if (unlikely(err))
goto free_dst; goto free_dst;
...@@ -699,9 +666,9 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb, ...@@ -699,9 +666,9 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
if (err) if (err)
goto free_dst; goto free_dst;
gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) +
geneve_build_header(gnvh, tun_flags, vni, opt_len, opt); info->options_len);
geneve_build_header(gnvh, info);
skb_set_inner_protocol(skb, htons(ETH_P_TEB)); skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return 0; return 0;
...@@ -709,12 +676,11 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb, ...@@ -709,12 +676,11 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
dst_release(dst); dst_release(dst);
return err; return err;
} }
#endif
static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
struct flowi4 *fl4, struct flowi4 *fl4,
struct ip_tunnel_info *info) const struct ip_tunnel_info *info)
{ {
bool use_cache = ip_tunnel_dst_cache_usable(skb, info); bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev); struct geneve_dev *geneve = netdev_priv(dev);
...@@ -738,7 +704,7 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, ...@@ -738,7 +704,7 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
} }
fl4->flowi4_tos = RT_TOS(tos); fl4->flowi4_tos = RT_TOS(tos);
dst_cache = &info->dst_cache; dst_cache = (struct dst_cache *)&info->dst_cache;
if (use_cache) { if (use_cache) {
rt = dst_cache_get_ip4(dst_cache, &fl4->saddr); rt = dst_cache_get_ip4(dst_cache, &fl4->saddr);
if (rt) if (rt)
...@@ -763,7 +729,7 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, ...@@ -763,7 +729,7 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
struct flowi6 *fl6, struct flowi6 *fl6,
struct ip_tunnel_info *info) const struct ip_tunnel_info *info)
{ {
bool use_cache = ip_tunnel_dst_cache_usable(skb, info); bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev); struct geneve_dev *geneve = netdev_priv(dev);
...@@ -789,7 +755,7 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, ...@@ -789,7 +755,7 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
fl6->flowlabel = ip6_make_flowinfo(RT_TOS(prio), fl6->flowlabel = ip6_make_flowinfo(RT_TOS(prio),
info->key.label); info->key.label);
dst_cache = &info->dst_cache; dst_cache = (struct dst_cache *)&info->dst_cache;
if (use_cache) { if (use_cache) {
dst = dst_cache_get_ip6(dst_cache, &fl6->saddr); dst = dst_cache_get_ip6(dst_cache, &fl6->saddr);
if (dst) if (dst)
...@@ -812,7 +778,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, ...@@ -812,7 +778,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
#endif #endif
static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct geneve_dev *geneve, struct ip_tunnel_info *info) struct geneve_dev *geneve,
const struct ip_tunnel_info *info)
{ {
bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
struct geneve_sock *gs4 = rcu_dereference(geneve->sock4); struct geneve_sock *gs4 = rcu_dereference(geneve->sock4);
...@@ -820,11 +787,9 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -820,11 +787,9 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct rtable *rt; struct rtable *rt;
int err = -EINVAL; int err = -EINVAL;
struct flowi4 fl4; struct flowi4 fl4;
u8 *opts = NULL;
__u8 tos, ttl; __u8 tos, ttl;
__be16 sport; __be16 sport;
__be16 df; __be16 df;
u8 vni[3];
if (!gs4) if (!gs4)
return err; return err;
...@@ -843,13 +808,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -843,13 +808,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
} }
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
tunnel_id_to_vni(key->tun_id, vni); err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr));
if (info->options_len)
opts = ip_tunnel_info_opts(info);
skb_reset_mac_header(skb);
err = geneve_build_skb(rt, skb, key->tun_flags, vni,
info->options_len, opts, xnet);
if (unlikely(err)) if (unlikely(err))
return err; return err;
...@@ -862,7 +821,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -862,7 +821,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct geneve_dev *geneve, struct ip_tunnel_info *info) struct geneve_dev *geneve,
const struct ip_tunnel_info *info)
{ {
bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
struct geneve_sock *gs6 = rcu_dereference(geneve->sock6); struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
...@@ -870,10 +830,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -870,10 +830,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct dst_entry *dst = NULL; struct dst_entry *dst = NULL;
int err = -EINVAL; int err = -EINVAL;
struct flowi6 fl6; struct flowi6 fl6;
u8 *opts = NULL;
__u8 prio, ttl; __u8 prio, ttl;
__be16 sport; __be16 sport;
u8 vni[3];
if (!gs6) if (!gs6)
return err; return err;
...@@ -891,13 +849,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -891,13 +849,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
ip_hdr(skb), skb); ip_hdr(skb), skb);
ttl = key->ttl ? : ip6_dst_hoplimit(dst); ttl = key->ttl ? : ip6_dst_hoplimit(dst);
} }
tunnel_id_to_vni(key->tun_id, vni); err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct iphdr));
if (info->options_len)
opts = ip_tunnel_info_opts(info);
skb_reset_mac_header(skb);
err = geneve6_build_skb(dst, skb, key->tun_flags, vni,
info->options_len, opts, xnet);
if (unlikely(err)) if (unlikely(err))
return err; return err;
......
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