@@ -836,7 +836,8 @@ free_dst:
static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
struct net_device *dev,
struct flowi4 *fl4,
- struct ip_tunnel_info *info)
+ struct ip_tunnel_info *info,
+ __be16 dport, __be16 sport)
{
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev);
@@ -850,6 +851,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
memset(fl4, 0, sizeof(*fl4));
fl4->flowi4_mark = skb->mark;
fl4->flowi4_proto = IPPROTO_UDP;
+ fl4->fl4_dport = dport;
+ fl4->fl4_sport = sport;
if (info) {
fl4->daddr = info->key.u.ipv4.dst;
@@ -895,7 +898,8 @@ 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)
+ struct ip_tunnel_info *info,
+ __be16 dport, __be16 sport)
{
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev);
@@ -911,6 +915,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
memset(fl6, 0, sizeof(*fl6));
fl6->flowi6_mark = skb->mark;
fl6->flowi6_proto = IPPROTO_UDP;
+ fl6->fl6_dport = dport;
+ fl6->fl6_sport = sport;
if (info) {
fl6->daddr = info->key.u.ipv6.dst;
@@ -1005,13 +1011,13 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
goto tx_error;
}
- rt = geneve_get_v4_rt(skb, dev, &fl4, info);
+ sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+ rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, sport);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
goto tx_error;
}
- sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
skb_reset_mac_header(skb);
iip = ip_hdr(skb);
@@ -1097,13 +1103,13 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
}
}
- dst = geneve_get_v6_dst(skb, dev, &fl6, info);
+ sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+ dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, sport);
if (IS_ERR(dst)) {
err = PTR_ERR(dst);
goto tx_error;
}
- sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
skb_reset_mac_header(skb);
iip = ip_hdr(skb);
@@ -1232,13 +1238,17 @@ int ovs_geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
struct geneve_dev *geneve = netdev_priv(dev);
struct rtable *rt;
struct flowi4 fl4;
+ __be16 sport;
#if IS_ENABLED(CONFIG_IPV6)
struct dst_entry *dst;
struct flowi6 fl6;
#endif
+ sport = udp_flow_src_port(geneve->net, skb,
+ 1, USHRT_MAX, true);
+
if (ip_tunnel_info_af(info) == AF_INET) {
- rt = geneve_get_v4_rt(skb, dev, &fl4, info);
+ rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, sport);
if (IS_ERR(rt))
return PTR_ERR(rt);
@@ -1246,7 +1256,7 @@ int ovs_geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
info->key.u.ipv4.src = fl4.saddr;
#if IS_ENABLED(CONFIG_IPV6)
} else if (ip_tunnel_info_af(info) == AF_INET6) {
- dst = geneve_get_v6_dst(skb, dev, &fl6, info);
+ dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, sport);
if (IS_ERR(dst))
return PTR_ERR(dst);
@@ -1257,8 +1267,7 @@ int ovs_geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
return -EINVAL;
}
- info->key.tp_src = udp_flow_src_port(geneve->net, skb,
- 1, USHRT_MAX, true);
+ info->key.tp_src = sport;
info->key.tp_dst = geneve->dst_port;
return 0;
}
@@ -979,7 +979,8 @@ err_free_rt:
static struct rtable *stt_get_rt(struct sk_buff *skb,
struct net_device *dev,
struct flowi4 *fl,
- const struct ip_tunnel_key *key)
+ const struct ip_tunnel_key *key,
+ __be16 dport, __be16 sport)
{
struct net *net = dev_net(dev);
@@ -990,6 +991,8 @@ static struct rtable *stt_get_rt(struct sk_buff *skb,
fl->flowi4_tos = RT_TOS(key->tos);
fl->flowi4_mark = skb->mark;
fl->flowi4_proto = IPPROTO_TCP;
+ fl->fl4_dport = dport;
+ fl->fl4_sport = sport;
return ip_route_output_key(net, fl);
}
@@ -1016,14 +1019,14 @@ netdev_tx_t ovs_stt_xmit(struct sk_buff *skb)
tun_key = &tun_info->key;
- rt = stt_get_rt(skb, dev, &fl, tun_key);
+ sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
+ rt = stt_get_rt(skb, dev, &fl, tun_key, dport, sport);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
goto error;
}
df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
- sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
skb->ignore_df = 1;
stt_xmit_skb(skb, rt, fl.saddr, tun_key->u.ipv4.dst,
@@ -1825,20 +1828,22 @@ int ovs_stt_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
struct stt_dev *stt_dev = netdev_priv(dev);
struct net *net = stt_dev->net;
__be16 dport = stt_dev->dst_port;
+ __be16 sport;
struct flowi4 fl4;
struct rtable *rt;
if (ip_tunnel_info_af(info) != AF_INET)
return -EINVAL;
- rt = stt_get_rt(skb, dev, &fl4, &info->key);
+ sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
+ rt = stt_get_rt(skb, dev, &fl4, &info->key, dport, sport);
if (IS_ERR(rt))
return PTR_ERR(rt);
ip_rt_put(rt);
info->key.u.ipv4.src = fl4.saddr;
- info->key.tp_src = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
+ info->key.tp_src = sport;
info->key.tp_dst = dport;
return 0;
}
@@ -896,6 +896,7 @@ out_free:
static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
struct sk_buff *skb, int oif, u8 tos,
__be32 daddr, __be32 *saddr,
+ __be16 dport, __be16 sport,
struct dst_cache *dst_cache,
const struct ip_tunnel_info *info)
{
@@ -918,6 +919,8 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
fl4.flowi4_proto = IPPROTO_UDP;
fl4.daddr = daddr;
fl4.saddr = *saddr;
+ fl4.fl4_dport = dport;
+ fl4.fl4_sport = sport;
rt = ip_route_output_key(vxlan->net, &fl4);
if (!IS_ERR(rt)) {
@@ -934,6 +937,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
__be32 label,
const struct in6_addr *daddr,
struct in6_addr *saddr,
+ __be16 dport, __be16 sport,
struct dst_cache *dst_cache,
const struct ip_tunnel_info *info)
{
@@ -961,6 +965,8 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label);
fl6.flowi6_mark = skb->mark;
fl6.flowi6_proto = IPPROTO_UDP;
+ fl6.fl6_dport = dport;
+ fl6.fl6_sport = sport;
#ifdef HAVE_IPV6_DST_LOOKUP_NET
err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
@@ -1090,6 +1096,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
rdst ? rdst->remote_ifindex : 0, tos,
dst->sin.sin_addr.s_addr,
&src->sin.sin_addr.s_addr,
+ dst_port, src_port,
dst_cache, info);
if (IS_ERR(rt)) {
netdev_dbg(dev, "no route to %pI4\n",
@@ -1149,6 +1156,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
rdst ? rdst->remote_ifindex : 0, tos,
label, &dst->sin6.sin6_addr,
&src->sin6.sin6_addr,
+ dst_port, src_port,
dst_cache, info);
if (IS_ERR(ndst)) {
netdev_dbg(dev, "no route to %pI6\n",
@@ -1439,7 +1447,8 @@ int ovs_vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
return -EINVAL;
rt = vxlan_get_route(vxlan, skb, 0, info->key.tos,
info->key.u.ipv4.dst,
- &info->key.u.ipv4.src, NULL, info);
+ &info->key.u.ipv4.src,
+ dport, sport, NULL, info);
if (IS_ERR(rt))
return PTR_ERR(rt);
ip_rt_put(rt);
@@ -1449,7 +1458,8 @@ int ovs_vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos,
info->key.label, &info->key.u.ipv6.dst,
- &info->key.u.ipv6.src, NULL, info);
+ &info->key.u.ipv6.src,
+ dport, sport, NULL, info);
if (IS_ERR(ndst))
return PTR_ERR(ndst);
dst_release(ndst);
This patch adds transport ports information for route lookup so that IPsec can select tunnel traffic (geneve, stt, vxlan) to do encryption. The patch was tested for geneve, stt, and vxlan tunnel and the results show that IPsec policy can be set to only match the corresponding tunnel traffic. Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com> --- datapath/linux/compat/geneve.c | 29 +++++++++++++++++++---------- datapath/linux/compat/stt.c | 15 ++++++++++----- datapath/linux/compat/vxlan.c | 14 ++++++++++++-- 3 files changed, 41 insertions(+), 17 deletions(-)