[ovs-dev] [PATCH] datapath: add transport ports in route lookup to enable IPsec policy match.

Qiuyu Xiao qiuyu.xiao.qyx at gmail.com
Mon Jun 18 18:14:53 UTC 2018


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 at 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(-)

diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
index 435a23f..95a665d 100644
--- a/datapath/linux/compat/geneve.c
+++ b/datapath/linux/compat/geneve.c
@@ -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;
 }
diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c
index 2426223..e689f78 100644
--- a/datapath/linux/compat/stt.c
+++ b/datapath/linux/compat/stt.c
@@ -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;
 }
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 7f5d5ce..b850fdd 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -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);
-- 
2.7.4



More information about the dev mailing list