diff mbox series

[ovs-dev,v3,1/6] datapath: add transport ports in route lookup to enable IPsec policy match.

Message ID 20180727204434.18525-2-qiuyu.xiao.qyx@gmail.com
State Superseded
Headers show
Series IPsec support for tunneling | expand

Commit Message

Qiuyu Xiao July 27, 2018, 8:44 p.m. UTC
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(-)

Comments

Ben Pfaff July 30, 2018, 4:49 p.m. UTC | #1
On Fri, Jul 27, 2018 at 01:44:29PM -0700, Qiuyu Xiao wrote:
> 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>

I think that this patch should probably be broken up into three:

1. Geneve changes.  These changes need to go to upstream Linux before
   we commit them to the OVS repo.

2. VXLAN changes.  As I understand it, similar changes are already
   upstream, so we can put them into OVS right away.

3. STT changes.  STT is not in upstream Linux, so we can put these into
   OVS right away too.

I think that Greg has already positively reviewed this.  Did he give you
an Acked-by tag?  If he did, then you should add it to the commit
message.
Qiuyu Xiao July 30, 2018, 4:56 p.m. UTC | #2
Greg gave me Reviewed-by and Tested-by tags. I will add those to
commit messages.

Thanks,
Qiuyu

On Mon, Jul 30, 2018 at 9:49 AM, Ben Pfaff <blp@ovn.org> wrote:
> On Fri, Jul 27, 2018 at 01:44:29PM -0700, Qiuyu Xiao wrote:
>> 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>
>
> I think that this patch should probably be broken up into three:
>
> 1. Geneve changes.  These changes need to go to upstream Linux before
>    we commit them to the OVS repo.
>
> 2. VXLAN changes.  As I understand it, similar changes are already
>    upstream, so we can put them into OVS right away.
>
> 3. STT changes.  STT is not in upstream Linux, so we can put these into
>    OVS right away too.
>
> I think that Greg has already positively reviewed this.  Did he give you
> an Acked-by tag?  If he did, then you should add it to the commit
> message.
diff mbox series

Patch

diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
index 435a23fb7..95a665ddd 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 2426223db..e689f7824 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 7f5d5ce64..b850fdd44 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);