[nf-next,v2,3/3] netfilter: using ip6tables as L2/L3/L4 classifier for SRv6

Message ID 20180822131018.11286-3-amsalam20@gmail.com
State Under Review
Delegated to: Pablo Neira
Headers show
Series
  • [nf-next,v2,1/3] netfilter: export SRH processing functions from seg6local
Related show

Commit Message

Ahmed Abdelsalam Aug. 22, 2018, 1:10 p.m.
In Linux, SRv6 policies can be pushed based on the destination
address of packets.

However for many use-cases, it is needed to push SRv6 policies
based on information from L2/L3/L4.

Consider a use-case where you want to push SRv6 policies based
on the application layer protocol (HTTP/DNS), which requires
being able to match the destination port of a packet.

In this patch, we use iptables a classifier for SRv6, hence we
benefit from all of its matching capabilities.

We added a new action to the SEG6 target, named "bind-sid",
that takes the BSID and the SID table as arguments.

Each packet that matches an iptables rule with SEG6 target that
has the bind-sid action, will go through the SRv6 policies
configured for that BSID.

Example:
We have an SRv6 policy configured in Linux as follows:
ip -6 route add A99::1 encap seg6 mode encap segs F1::,F2:: dev eth1

We can steer traffic through this SRv6 policy using the matching
power of iptables firewall as follows:

ip6atbles -t raw -I PREROUTING -s <saddr> -d <daddr> \
-p <proto> --sport <src_port> --dport <dst_port> \
-j SEG6 --seg6-action bind-sid --bsid A99::1 --bsid-tbl 0

This new SEG6 action should perfectly address all use-cases that
require pushing SRv6 policies based information from Layer3/Layer4.

Signed-off-by: Ahmed Abdelsalam <amsalam20@gmail.com>
---
 net/ipv6/netfilter/ip6t_SEG6.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

Patch

diff --git a/net/ipv6/netfilter/ip6t_SEG6.c b/net/ipv6/netfilter/ip6t_SEG6.c
index 0adfb98ccaf2..283786cf4126 100644
--- a/net/ipv6/netfilter/ip6t_SEG6.c
+++ b/net/ipv6/netfilter/ip6t_SEG6.c
@@ -25,6 +25,14 @@ 
 #include <net/seg6.h>
 #include <net/ip6_route.h>
 
+static int seg6_bsid(struct sk_buff *skb, struct in6_addr bsid,
+		     u32 tbl)
+{
+	seg6_lookup_nexthop(skb, &bsid, tbl);
+	dst_input(skb);
+	return NF_STOLEN;
+}
+
 static int seg6_go_next(struct sk_buff *skb, struct ipv6_sr_hdr *srh)
 {
 	if (srh->segments_left == 0)
@@ -63,6 +71,10 @@  seg6_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 	struct ipv6_sr_hdr *srh;
 	const struct ip6t_seg6_info *seg6 = par->targinfo;
 
+	/* bind-sid action doesn't require packets with SRH */
+	if (seg6->action == IP6T_SEG6_BSID)
+		return seg6_bsid(skb, seg6->bsid, seg6->tbl);
+
 	srh = seg6_get_srh(skb);
 	if (!srh)
 		return NF_DROP;
@@ -87,6 +99,7 @@  static int seg6_check(const struct xt_tgchk_param *par)
 	case IP6T_SEG6_GO_NEXT:
 	case IP6T_SEG6_SKIP_NEXT:
 	case IP6T_SEG6_GO_LAST:
+	case IP6T_SEG6_BSID:
 		return 0;
 	default:
 	return -EOPNOTSUPP;