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: Pravin B Shelar <pshelar@ovn.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9b4437a5b8
commit
c3ef5aa5e5
@ -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);
|
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(rt->dst.dev) + rt->dst.header_len
|
min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len +
|
||||||
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr);
|
GENEVE_BASE_HLEN + info->options_len + ip_hdr_len;
|
||||||
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);
|
|
||||||
struct genevehdr *gnvh;
|
|
||||||
int min_headroom;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
skb_scrub_packet(skb, xnet);
|
|
||||||
|
|
||||||
min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
|
|
||||||
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr);
|
|
||||||
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,
|
|||||||
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 @@ free_dst:
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
#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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
|
|
||||||
#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,
|
|||||||
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,
|
|||||||
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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user