Skip to content

Commit 51cb87c

Browse files
committed
Merge branch 'ipv6-sr-add-support-for-advanced-local-segment-processing'
David Lebrun says: ==================== ipv6: sr: add support for advanced local segment processing v2: use EXPORT_SYMBOL_GPL The current implementation of IPv6 SR supports SRH insertion/encapsulation and basic segment endpoint behavior (i.e., processing of an SRH contained in a packet whose active segment (IPv6 DA) is routed to the local node). This behavior simply consists of updating the DA to the next segment and forwarding the packet accordingly. This processing is realised for all such packets, regardless of the active segment. The most recent specifications of IPv6 SR [1] [2] extend the SRH processing features as follows. Each segment endpoint defines a MyLocalSID table. This table maps segments to operations to perform. For each ingress IPv6 packet whose DA is part of a given prefix, the segment endpoint looks up the active segment (i.e., the IPv6 DA) in the MyLocalSID table and applies the corresponding operation. Such specifications enable to specify arbitrary operations besides the basic SRH processing and allow for a more fine-grained classification. This patch series implements those extended specifications by leveraging a new type of lightweight tunnel, seg6local. The MyLocalSID table is simply an arbitrary routing table (using CONFIG_IPV6_MULTIPLE_TABLES). The following commands would assign the prefix fc00::/64 to the MyLocalSID table, map the segment fc00::42 to the regular SRH processing function (named "End"), and drop all packets received with an undefined active segment: ip -6 rule add fc00::/64 lookup 100 ip -6 route add fc00::42 encap seg6local action End dev eth0 table 100 ip -6 route add blackhole default table 100 As another example, the following command would assign the segment fc00::1234 to the regular SRH processing function, except that the processed packet must be forwarded to the next-hop fc42::1 (this operation is named "End.X"): ip -6 route add fc00::1234 encap seg6local action End.X nh6 fc42::1 dev eth0 table 100 Those two basic operations (End and End.X) are defined in [1]. A more extensive list of advanced operations is defined in [2]. The first two patches of the series are preliminary work that remove an assumption about initial SRH format, and export the two functions used to insert and encapsulate an SRH onto packets. The third patch defines the new seg6local lightweight tunnel and implement the core functions. The fourth patch implements the operations needed to handle the newly defined rtnetlink attributes. The fifth patch implements a few SRH processing operations, including End and End.X. [1] https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07 [2] https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-01 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 4cc7b95 + 140f04c commit 51cb87c

File tree

11 files changed

+862
-25
lines changed

11 files changed

+862
-25
lines changed

include/linux/seg6_local.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef _LINUX_SEG6_LOCAL_H
2+
#define _LINUX_SEG6_LOCAL_H
3+
4+
#include <uapi/linux/seg6_local.h>
5+
6+
#endif

include/net/seg6.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ extern int seg6_init(void);
5656
extern void seg6_exit(void);
5757
extern int seg6_iptunnel_init(void);
5858
extern void seg6_iptunnel_exit(void);
59+
extern int seg6_local_init(void);
60+
extern void seg6_local_exit(void);
5961

6062
extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len);
63+
extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
64+
extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh);
6165

6266
#endif

include/uapi/linux/lwtunnel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ enum lwtunnel_encap_types {
1111
LWTUNNEL_ENCAP_IP6,
1212
LWTUNNEL_ENCAP_SEG6,
1313
LWTUNNEL_ENCAP_BPF,
14+
LWTUNNEL_ENCAP_SEG6_LOCAL,
1415
__LWTUNNEL_ENCAP_MAX,
1516
};
1617

include/uapi/linux/seg6_local.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* SR-IPv6 implementation
3+
*
4+
* Author:
5+
* David Lebrun <david.lebrun@uclouvain.be>
6+
*
7+
*
8+
* This program is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU General Public License
10+
* as published by the Free Software Foundation; either version
11+
* 2 of the License, or (at your option) any later version.
12+
*/
13+
14+
#ifndef _UAPI_LINUX_SEG6_LOCAL_H
15+
#define _UAPI_LINUX_SEG6_LOCAL_H
16+
17+
#include <linux/seg6.h>
18+
19+
enum {
20+
SEG6_LOCAL_UNSPEC,
21+
SEG6_LOCAL_ACTION,
22+
SEG6_LOCAL_SRH,
23+
SEG6_LOCAL_TABLE,
24+
SEG6_LOCAL_NH4,
25+
SEG6_LOCAL_NH6,
26+
SEG6_LOCAL_IIF,
27+
SEG6_LOCAL_OIF,
28+
__SEG6_LOCAL_MAX,
29+
};
30+
#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
31+
32+
enum {
33+
SEG6_LOCAL_ACTION_UNSPEC = 0,
34+
/* node segment */
35+
SEG6_LOCAL_ACTION_END = 1,
36+
/* adjacency segment (IPv6 cross-connect) */
37+
SEG6_LOCAL_ACTION_END_X = 2,
38+
/* lookup of next seg NH in table */
39+
SEG6_LOCAL_ACTION_END_T = 3,
40+
/* decap and L2 cross-connect */
41+
SEG6_LOCAL_ACTION_END_DX2 = 4,
42+
/* decap and IPv6 cross-connect */
43+
SEG6_LOCAL_ACTION_END_DX6 = 5,
44+
/* decap and IPv4 cross-connect */
45+
SEG6_LOCAL_ACTION_END_DX4 = 6,
46+
/* decap and lookup of DA in v6 table */
47+
SEG6_LOCAL_ACTION_END_DT6 = 7,
48+
/* decap and lookup of DA in v4 table */
49+
SEG6_LOCAL_ACTION_END_DT4 = 8,
50+
/* binding segment with insertion */
51+
SEG6_LOCAL_ACTION_END_B6 = 9,
52+
/* binding segment with encapsulation */
53+
SEG6_LOCAL_ACTION_END_B6_ENCAP = 10,
54+
/* binding segment with MPLS encap */
55+
SEG6_LOCAL_ACTION_END_BM = 11,
56+
/* lookup last seg in table */
57+
SEG6_LOCAL_ACTION_END_S = 12,
58+
/* forward to SR-unaware VNF with static proxy */
59+
SEG6_LOCAL_ACTION_END_AS = 13,
60+
/* forward to SR-unaware VNF with masquerading */
61+
SEG6_LOCAL_ACTION_END_AM = 14,
62+
63+
__SEG6_LOCAL_ACTION_MAX,
64+
};
65+
66+
#define SEG6_LOCAL_ACTION_MAX (__SEG6_LOCAL_ACTION_MAX - 1)
67+
68+
#endif

net/core/lwtunnel.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
4444
return "SEG6";
4545
case LWTUNNEL_ENCAP_BPF:
4646
return "BPF";
47+
case LWTUNNEL_ENCAP_SEG6_LOCAL:
48+
return "SEG6LOCAL";
4749
case LWTUNNEL_ENCAP_IP6:
4850
case LWTUNNEL_ENCAP_IP:
4951
case LWTUNNEL_ENCAP_NONE:

net/ipv6/Kconfig

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -311,19 +311,8 @@ config IPV6_SEG6_LWTUNNEL
311311
---help---
312312
Support for encapsulation of packets within an outer IPv6
313313
header and a Segment Routing Header using the lightweight
314-
tunnels mechanism.
315-
316-
If unsure, say N.
317-
318-
config IPV6_SEG6_INLINE
319-
bool "IPv6: direct Segment Routing Header insertion "
320-
depends on IPV6_SEG6_LWTUNNEL
321-
---help---
322-
Support for direct insertion of the Segment Routing Header,
323-
also known as inline mode. Be aware that direct insertion of
324-
extension headers (as opposed to encapsulation) may break
325-
multiple mechanisms such as PMTUD or IPSec AH. Use this feature
326-
only if you know exactly what you are doing.
314+
tunnels mechanism. Also enable support for advanced local
315+
processing of SRv6 packets based on their active segment.
327316

328317
If unsure, say N.
329318

net/ipv6/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
2323
ipv6-$(CONFIG_PROC_FS) += proc.o
2424
ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
2525
ipv6-$(CONFIG_NETLABEL) += calipso.o
26-
ipv6-$(CONFIG_IPV6_SEG6_LWTUNNEL) += seg6_iptunnel.o
26+
ipv6-$(CONFIG_IPV6_SEG6_LWTUNNEL) += seg6_iptunnel.o seg6_local.o
2727
ipv6-$(CONFIG_IPV6_SEG6_HMAC) += seg6_hmac.o
2828

2929
ipv6-objs += $(ipv6-y)

net/ipv6/exthdrs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto,
882882
(hops - 1) * sizeof(struct in6_addr));
883883

884884
sr_phdr->segments[0] = **addr_p;
885-
*addr_p = &sr_ihdr->segments[hops - 1];
885+
*addr_p = &sr_ihdr->segments[sr_ihdr->segments_left];
886886

887887
#ifdef CONFIG_IPV6_SEG6_HMAC
888888
if (sr_has_hmac(sr_phdr)) {
@@ -1174,7 +1174,7 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
11741174
{
11751175
struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)opt->srcrt;
11761176

1177-
fl6->daddr = srh->segments[srh->first_segment];
1177+
fl6->daddr = srh->segments[srh->segments_left];
11781178
break;
11791179
}
11801180
default:

net/ipv6/seg6.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len)
4040
if (((srh->hdrlen + 1) << 3) != len)
4141
return false;
4242

43-
if (srh->segments_left != srh->first_segment)
43+
if (srh->segments_left > srh->first_segment)
4444
return false;
4545

4646
tlv_offset = sizeof(*srh) + ((srh->first_segment + 1) << 4);
@@ -456,6 +456,10 @@ int __init seg6_init(void)
456456
err = seg6_iptunnel_init();
457457
if (err)
458458
goto out_unregister_pernet;
459+
460+
err = seg6_local_init();
461+
if (err)
462+
goto out_unregister_pernet;
459463
#endif
460464

461465
#ifdef CONFIG_IPV6_SEG6_HMAC
@@ -471,6 +475,7 @@ int __init seg6_init(void)
471475
#ifdef CONFIG_IPV6_SEG6_HMAC
472476
out_unregister_iptun:
473477
#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
478+
seg6_local_exit();
474479
seg6_iptunnel_exit();
475480
#endif
476481
#endif

net/ipv6/seg6_iptunnel.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static void set_tun_src(struct net *net, struct net_device *dev,
9191
}
9292

9393
/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
94-
static int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
94+
int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
9595
{
9696
struct net *net = dev_net(skb_dst(skb)->dev);
9797
struct ipv6hdr *hdr, *inner_hdr;
@@ -141,10 +141,10 @@ static int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
141141

142142
return 0;
143143
}
144+
EXPORT_SYMBOL_GPL(seg6_do_srh_encap);
144145

145146
/* insert an SRH within an IPv6 packet, just after the IPv6 header */
146-
#ifdef CONFIG_IPV6_SEG6_INLINE
147-
static int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
147+
int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
148148
{
149149
struct ipv6hdr *hdr, *oldhdr;
150150
struct ipv6_sr_hdr *isrh;
@@ -193,7 +193,7 @@ static int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
193193

194194
return 0;
195195
}
196-
#endif
196+
EXPORT_SYMBOL_GPL(seg6_do_srh_inline);
197197

198198
static int seg6_do_srh(struct sk_buff *skb)
199199
{
@@ -209,12 +209,10 @@ static int seg6_do_srh(struct sk_buff *skb)
209209
}
210210

211211
switch (tinfo->mode) {
212-
#ifdef CONFIG_IPV6_SEG6_INLINE
213212
case SEG6_IPTUN_MODE_INLINE:
214213
err = seg6_do_srh_inline(skb, tinfo->srh);
215214
skb_reset_inner_headers(skb);
216215
break;
217-
#endif
218216
case SEG6_IPTUN_MODE_ENCAP:
219217
err = seg6_do_srh_encap(skb, tinfo->srh);
220218
break;
@@ -357,10 +355,8 @@ static int seg6_build_state(struct nlattr *nla,
357355
return -EINVAL;
358356

359357
switch (tuninfo->mode) {
360-
#ifdef CONFIG_IPV6_SEG6_INLINE
361358
case SEG6_IPTUN_MODE_INLINE:
362359
break;
363-
#endif
364360
case SEG6_IPTUN_MODE_ENCAP:
365361
break;
366362
default:

0 commit comments

Comments
 (0)