-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
David Lebrun says: ==================== net: add support for IPv6 Segment Routing v5: - Check SRH validity when adding a new route with lwtunnels and when setting an IPV6_RTHDR socket option. - Check that hdr->segments_left is not out of bounds when processing an SR-enabled packet. - Add __ro_after_init attribute to seg6_genl_policy structure. - Add CONFIG_IPV6_SEG6_INLINE option to enable or disable direct header insertion. v4: - Change @cleanup in ipv6_srh_rcv() from int to bool - Move checksum helper functions into header file - Add common definition for SR TLVs - Add comments for HMAC computation algorithm - Use rhashtable to store HMAC infos instead of linked list - Remove packed attribute for struct sr6_tlv_hmac - Use dst cache only if CONFIG_DST_CACHE is enabled v3: - Fix compilation for CONFIG_IPV6={n,m} v2: - Remove packed attribute from sr6 struct and replaced unaligned 16-bit flags with two 8-bit flags. - SR code now included by default. Option CONFIG_IPV6_SEG6_HMAC exists for HMAC support (which requires crypto dependencies). - Replace "hidden" calls to mutex_{un,}lock to direct calls. - Fix reverse xmas tree coding style. - Fix cast-from-void*'s. - Update skb->csum to account for SR modifications. - Add dst_cache in seg6_output. Segment Routing (SR) is a source routing paradigm, architecturally defined in draft-ietf-spring-segment-routing-09 [1]. The IPv6 flavor of SR is defined in draft-ietf-6man-segment-routing-header-02 [2]. The main idea is that an SR-enabled packet contains a list of segments, which represent mandatory waypoints. Each waypoint is called a segment endpoint. The SR-enabled packet is routed normally (e.g. shortest path) between the segment endpoints. A node that inserts an SRH into a packet is called an ingress node, and a node that is the last segment endpoint is called an egress node. From an IPv6 viewpoint, an SR-enabled packet contains an IPv6 extension header, which is a Routing Header type 4, defined as follows: struct ipv6_sr_hdr { __u8 nexthdr; __u8 hdrlen; __u8 type; __u8 segments_left; __u8 first_segment; __u8 flag_1; __u8 flag_2; __u8 reserved; struct in6_addr segments[0]; }; The first 4 bytes of the SRH is consistent with the Routing Header definition in RFC 2460. The type is set to `4' (SRH). Each segment is encoded as an IPv6 address. The segments are encoded in reverse order: segments[0] is the last segment of the path, and segments[first_segment] is the first segment of the path. segments[segments_left] points to the currently active segment and segments_left is decremented at each segment endpoint. There exist two ways for a packet to receive an SRH, we call them encap mode and inline mode. In the encap mode, the packet is encapsulated in an outer IPv6 header that contains the SRH. The inner (original) packet is not modified. A virtual tunnel is thus created between the ingress node (the node that encapsulates) and the egress node (the last segment of the path). Once an encapsulated SR packet reaches the egress node, the node decapsulates the packet and performs a routing decision on the inner packet. This kind of SRH insertion is intended to use for routers that encapsulates in-transit packet. The second SRH insertion method, the inline mode, acts by directly inserting the SRH right after the IPv6 header of the original packet. For this method, if a particular flag (SR6_FLAG_CLEANUP) is set, then the penultimate segment endpoint must strip the SRH from the packet before forwarding it to the last segment endpoint. This insertion method is intended to use for endhosts, however it is also used for in-transit packets by some industry actors. Note that directly inserting extension headers may break several mechanisms such as Path MTU Discovery, IPSec AH, etc. For this reason, this insertion method is only available if CONFIG_IPV6_SEG6_INLINE is enabled. Finally, the SRH may contain TLVs after the segments list. Several types of TLVs are defined, but we currently consider only the HMAC TLV. This TLV is an answer to the deprecation of the RH0 and enables to ensure the authenticity and integrity of the SRH. The HMAC text contains the flags, the first_segment index, the full list of segments, and the source address of the packet. While SR is intended to use mostly within a single administrative domain, the HMAC TLV allows to verify SR packets coming from an untrusted source. This patches series implements support for the IPv6 flavor of SR and is logically divided into the following components: (1) Data plane support (patch 01). This patch adds a function in net/ipv6/exthdrs.c to handle the Routing Header type 4. It enables the kernel to act as a segment endpoint, by supporting the following operations: decrementation of the segments_left field, cleanup flag support (removal of the SRH if we are the penultimate segment endpoint) and decapsulation of the inner packet as an egress node. (2) Control plane support (patches 02..03 and 07..09). These patches enables to insert SRH on locally emitted and/or forwarded packets, both with encap mode and with inline mode. The SRH insertion is controlled through the lightweight tunnels mechanism. Furthermore, patch 08 enables the applications to insert an SRH on a per-socket basis, through the setsockopt() system call. The mechanism to specify a per-socket Routing Header was already defined for RH0 and no special modification was performed on this side. However, the code to actually push the RH onto the packets had to be adapted for the SRH specifications. (3) HMAC support (patches 04..06). These patches adds the support of the HMAC TLV verification for the dataplane part, and generation for the control plane part. Two hashing algorithms are supported (SHA-1 as legacy and SHA-256 as required by the IETF draft), but additional algorithms can be easily supported by simply adding an entry into an array. [1] https://tools.ietf.org/html/draft-ietf-spring-segment-routing-09 [2] https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-02 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Showing
28 changed files
with
2,070 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/proc/sys/net/conf/<iface>/seg6_* variables: | ||
|
||
seg6_enabled - BOOL | ||
Accept or drop SR-enabled IPv6 packets on this interface. | ||
|
||
Relevant packets are those with SRH present and DA = local. | ||
|
||
0 - disabled (default) | ||
not 0 - enabled | ||
|
||
seg6_require_hmac - INTEGER | ||
Define HMAC policy for ingress SR-enabled packets on this interface. | ||
|
||
-1 - Ignore HMAC field | ||
0 - Accept SR packets without HMAC, validate SR packets with HMAC | ||
1 - Drop SR packets without HMAC, validate SR packets with HMAC | ||
|
||
Default is 0. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef _LINUX_SEG6_H | ||
#define _LINUX_SEG6_H | ||
|
||
#include <uapi/linux/seg6.h> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef _LINUX_SEG6_GENL_H | ||
#define _LINUX_SEG6_GENL_H | ||
|
||
#include <uapi/linux/seg6_genl.h> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef _LINUX_SEG6_HMAC_H | ||
#define _LINUX_SEG6_HMAC_H | ||
|
||
#include <uapi/linux/seg6_hmac.h> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef _LINUX_SEG6_IPTUNNEL_H | ||
#define _LINUX_SEG6_IPTUNNEL_H | ||
|
||
#include <uapi/linux/seg6_iptunnel.h> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* SR-IPv6 implementation | ||
* | ||
* Author: | ||
* David Lebrun <david.lebrun@uclouvain.be> | ||
* | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
*/ | ||
|
||
#ifndef _NET_SEG6_H | ||
#define _NET_SEG6_H | ||
|
||
#include <linux/net.h> | ||
#include <linux/ipv6.h> | ||
#include <net/lwtunnel.h> | ||
#include <linux/seg6.h> | ||
#include <linux/rhashtable.h> | ||
|
||
static inline void update_csum_diff4(struct sk_buff *skb, __be32 from, | ||
__be32 to) | ||
{ | ||
__be32 diff[] = { ~from, to }; | ||
|
||
skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum); | ||
} | ||
|
||
static inline void update_csum_diff16(struct sk_buff *skb, __be32 *from, | ||
__be32 *to) | ||
{ | ||
__be32 diff[] = { | ||
~from[0], ~from[1], ~from[2], ~from[3], | ||
to[0], to[1], to[2], to[3], | ||
}; | ||
|
||
skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum); | ||
} | ||
|
||
struct seg6_pernet_data { | ||
struct mutex lock; | ||
struct in6_addr __rcu *tun_src; | ||
#ifdef CONFIG_IPV6_SEG6_HMAC | ||
struct rhashtable hmac_infos; | ||
#endif | ||
}; | ||
|
||
static inline struct seg6_pernet_data *seg6_pernet(struct net *net) | ||
{ | ||
return net->ipv6.seg6_data; | ||
} | ||
|
||
extern int seg6_init(void); | ||
extern void seg6_exit(void); | ||
extern int seg6_iptunnel_init(void); | ||
extern void seg6_iptunnel_exit(void); | ||
|
||
extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* SR-IPv6 implementation | ||
* | ||
* Author: | ||
* David Lebrun <david.lebrun@uclouvain.be> | ||
* | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
*/ | ||
|
||
#ifndef _NET_SEG6_HMAC_H | ||
#define _NET_SEG6_HMAC_H | ||
|
||
#include <net/flow.h> | ||
#include <net/ip6_fib.h> | ||
#include <net/sock.h> | ||
#include <linux/ip.h> | ||
#include <linux/ipv6.h> | ||
#include <linux/route.h> | ||
#include <net/seg6.h> | ||
#include <linux/seg6_hmac.h> | ||
#include <linux/rhashtable.h> | ||
|
||
#define SEG6_HMAC_MAX_DIGESTSIZE 160 | ||
#define SEG6_HMAC_RING_SIZE 256 | ||
|
||
struct seg6_hmac_info { | ||
struct rhash_head node; | ||
struct rcu_head rcu; | ||
|
||
u32 hmackeyid; | ||
char secret[SEG6_HMAC_SECRET_LEN]; | ||
u8 slen; | ||
u8 alg_id; | ||
}; | ||
|
||
struct seg6_hmac_algo { | ||
u8 alg_id; | ||
char name[64]; | ||
struct crypto_shash * __percpu *tfms; | ||
struct shash_desc * __percpu *shashs; | ||
}; | ||
|
||
extern int seg6_hmac_compute(struct seg6_hmac_info *hinfo, | ||
struct ipv6_sr_hdr *hdr, struct in6_addr *saddr, | ||
u8 *output); | ||
extern struct seg6_hmac_info *seg6_hmac_info_lookup(struct net *net, u32 key); | ||
extern int seg6_hmac_info_add(struct net *net, u32 key, | ||
struct seg6_hmac_info *hinfo); | ||
extern int seg6_hmac_info_del(struct net *net, u32 key); | ||
extern int seg6_push_hmac(struct net *net, struct in6_addr *saddr, | ||
struct ipv6_sr_hdr *srh); | ||
extern bool seg6_hmac_validate_skb(struct sk_buff *skb); | ||
extern int seg6_hmac_init(void); | ||
extern void seg6_hmac_exit(void); | ||
extern int seg6_hmac_net_init(struct net *net); | ||
extern void seg6_hmac_net_exit(struct net *net); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* SR-IPv6 implementation | ||
* | ||
* Author: | ||
* David Lebrun <david.lebrun@uclouvain.be> | ||
* | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
*/ | ||
|
||
#ifndef _UAPI_LINUX_SEG6_H | ||
#define _UAPI_LINUX_SEG6_H | ||
|
||
/* | ||
* SRH | ||
*/ | ||
struct ipv6_sr_hdr { | ||
__u8 nexthdr; | ||
__u8 hdrlen; | ||
__u8 type; | ||
__u8 segments_left; | ||
__u8 first_segment; | ||
__u8 flag_1; | ||
__u8 flag_2; | ||
__u8 reserved; | ||
|
||
struct in6_addr segments[0]; | ||
}; | ||
|
||
#define SR6_FLAG1_CLEANUP (1 << 7) | ||
#define SR6_FLAG1_PROTECTED (1 << 6) | ||
#define SR6_FLAG1_OAM (1 << 5) | ||
#define SR6_FLAG1_ALERT (1 << 4) | ||
#define SR6_FLAG1_HMAC (1 << 3) | ||
|
||
#define SR6_TLV_INGRESS 1 | ||
#define SR6_TLV_EGRESS 2 | ||
#define SR6_TLV_OPAQUE 3 | ||
#define SR6_TLV_PADDING 4 | ||
#define SR6_TLV_HMAC 5 | ||
|
||
#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP) | ||
#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC) | ||
|
||
struct sr6_tlv { | ||
__u8 type; | ||
__u8 len; | ||
__u8 data[0]; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#ifndef _UAPI_LINUX_SEG6_GENL_H | ||
#define _UAPI_LINUX_SEG6_GENL_H | ||
|
||
#define SEG6_GENL_NAME "SEG6" | ||
#define SEG6_GENL_VERSION 0x1 | ||
|
||
enum { | ||
SEG6_ATTR_UNSPEC, | ||
SEG6_ATTR_DST, | ||
SEG6_ATTR_DSTLEN, | ||
SEG6_ATTR_HMACKEYID, | ||
SEG6_ATTR_SECRET, | ||
SEG6_ATTR_SECRETLEN, | ||
SEG6_ATTR_ALGID, | ||
SEG6_ATTR_HMACINFO, | ||
__SEG6_ATTR_MAX, | ||
}; | ||
|
||
#define SEG6_ATTR_MAX (__SEG6_ATTR_MAX - 1) | ||
|
||
enum { | ||
SEG6_CMD_UNSPEC, | ||
SEG6_CMD_SETHMAC, | ||
SEG6_CMD_DUMPHMAC, | ||
SEG6_CMD_SET_TUNSRC, | ||
SEG6_CMD_GET_TUNSRC, | ||
__SEG6_CMD_MAX, | ||
}; | ||
|
||
#define SEG6_CMD_MAX (__SEG6_CMD_MAX - 1) | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#ifndef _UAPI_LINUX_SEG6_HMAC_H | ||
#define _UAPI_LINUX_SEG6_HMAC_H | ||
|
||
#include <linux/seg6.h> | ||
|
||
#define SEG6_HMAC_SECRET_LEN 64 | ||
#define SEG6_HMAC_FIELD_LEN 32 | ||
|
||
struct sr6_tlv_hmac { | ||
struct sr6_tlv tlvhdr; | ||
__u16 reserved; | ||
__be32 hmackeyid; | ||
__u8 hmac[SEG6_HMAC_FIELD_LEN]; | ||
}; | ||
|
||
enum { | ||
SEG6_HMAC_ALGO_SHA1 = 1, | ||
SEG6_HMAC_ALGO_SHA256 = 2, | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* SR-IPv6 implementation | ||
* | ||
* Author: | ||
* David Lebrun <david.lebrun@uclouvain.be> | ||
* | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
*/ | ||
|
||
#ifndef _UAPI_LINUX_SEG6_IPTUNNEL_H | ||
#define _UAPI_LINUX_SEG6_IPTUNNEL_H | ||
|
||
enum { | ||
SEG6_IPTUNNEL_UNSPEC, | ||
SEG6_IPTUNNEL_SRH, | ||
__SEG6_IPTUNNEL_MAX, | ||
}; | ||
#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1) | ||
|
||
struct seg6_iptunnel_encap { | ||
int mode; | ||
struct ipv6_sr_hdr srh[0]; | ||
}; | ||
|
||
#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3)) | ||
|
||
enum { | ||
SEG6_IPTUN_MODE_INLINE, | ||
SEG6_IPTUN_MODE_ENCAP, | ||
}; | ||
|
||
static inline size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo) | ||
{ | ||
int encap = (tuninfo->mode == SEG6_IPTUN_MODE_ENCAP); | ||
|
||
return ((tuninfo->srh->hdrlen + 1) << 3) + | ||
(encap * sizeof(struct ipv6hdr)); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.