Skip to content

Commit

Permalink
geneve: Merge ipv4 and ipv6 geneve_build_skb()
Browse files Browse the repository at this point in the history
There are minimal difference in building Geneve header
between ipv4 and ipv6 geneve tunnels. Following patch
refactors code to unify it.

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
pravin shelar authored and David S. Miller committed Nov 21, 2016
1 parent 9b4437a commit c3ef5aa
Showing 1 changed file with 26 additions and 74 deletions.
100 changes: 26 additions & 74 deletions drivers/net/geneve.c
Original file line number Diff line number Diff line change
Expand Up @@ -630,67 +630,34 @@ static int geneve_stop(struct net_device *dev)
}

static void geneve_build_header(struct genevehdr *geneveh,
__be16 tun_flags, u8 vni[3],
u8 options_len, u8 *options)
const struct ip_tunnel_info *info)
{
geneveh->ver = GENEVE_VER;
geneveh->opt_len = options_len / 4;
geneveh->oam = !!(tun_flags & TUNNEL_OAM);
geneveh->critical = !!(tun_flags & TUNNEL_CRIT_OPT);
geneveh->opt_len = info->options_len / 4;
geneveh->oam = !!(info->key.tun_flags & TUNNEL_OAM);
geneveh->critical = !!(info->key.tun_flags & TUNNEL_CRIT_OPT);
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->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,
__be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
bool xnet)
{
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)
static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
const struct ip_tunnel_info *info,
bool xnet, int ip_hdr_len)
{
bool udp_sum = !!(tun_flags & TUNNEL_CSUM);
bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
struct genevehdr *gnvh;
int min_headroom;
int err;

skb_reset_mac_header(skb);
skb_scrub_packet(skb, xnet);

min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr);
min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len +
GENEVE_BASE_HLEN + info->options_len + ip_hdr_len;
err = skb_cow_head(skb, min_headroom);
if (unlikely(err))
goto free_dst;
Expand All @@ -699,22 +666,21 @@ static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
if (err)
goto free_dst;

gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
geneve_build_header(gnvh, tun_flags, vni, opt_len, opt);

gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) +
info->options_len);
geneve_build_header(gnvh, info);
skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return 0;

free_dst:
dst_release(dst);
return err;
}
#endif

static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
struct net_device *dev,
struct flowi4 *fl4,
struct ip_tunnel_info *info)
const struct ip_tunnel_info *info)
{
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev);
Expand All @@ -738,7 +704,7 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
}
fl4->flowi4_tos = RT_TOS(tos);

dst_cache = &info->dst_cache;
dst_cache = (struct dst_cache *)&info->dst_cache;
if (use_cache) {
rt = dst_cache_get_ip4(dst_cache, &fl4->saddr);
if (rt)
Expand All @@ -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,
struct net_device *dev,
struct flowi6 *fl6,
struct ip_tunnel_info *info)
const struct ip_tunnel_info *info)
{
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev);
Expand All @@ -789,7 +755,7 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,

fl6->flowlabel = ip6_make_flowinfo(RT_TOS(prio),
info->key.label);
dst_cache = &info->dst_cache;
dst_cache = (struct dst_cache *)&info->dst_cache;
if (use_cache) {
dst = dst_cache_get_ip6(dst_cache, &fl6->saddr);
if (dst)
Expand All @@ -812,19 +778,18 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
#endif

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));
struct geneve_sock *gs4 = rcu_dereference(geneve->sock4);
const struct ip_tunnel_key *key = &info->key;
struct rtable *rt;
int err = -EINVAL;
struct flowi4 fl4;
u8 *opts = NULL;
__u8 tos, ttl;
__be16 sport;
__be16 df;
u8 vni[3];

if (!gs4)
return err;
Expand All @@ -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;

tunnel_id_to_vni(key->tun_id, vni);
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);
err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr));
if (unlikely(err))
return err;

Expand All @@ -862,18 +821,17 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,

#if IS_ENABLED(CONFIG_IPV6)
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));
struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
const struct ip_tunnel_key *key = &info->key;
struct dst_entry *dst = NULL;
int err = -EINVAL;
struct flowi6 fl6;
u8 *opts = NULL;
__u8 prio, ttl;
__be16 sport;
u8 vni[3];

if (!gs6)
return err;
Expand All @@ -891,13 +849,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
ip_hdr(skb), skb);
ttl = key->ttl ? : ip6_dst_hoplimit(dst);
}
tunnel_id_to_vni(key->tun_id, vni);
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);
err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct iphdr));
if (unlikely(err))
return err;

Expand Down

0 comments on commit c3ef5aa

Please sign in to comment.