Skip to content

Commit 1f0b774

Browse files
yi-y-yangdavem330
authored andcommitted
net: add NSH header structures and helpers
NSH (Network Service Header)[1] is a new protocol for service function chaining, it can be handled as a L3 protocol like IPv4 and IPv6, Eth + NSH + Inner packet or VxLAN-gpe + NSH + Inner packet are two typical use cases. This patch adds NSH header structures and helpers for NSH GSO support and Open vSwitch NSH support. [1] https://datatracker.ietf.org/doc/draft-ietf-sfc-nsh/ [Jiri: added nsh_hdr() helper and renamed the header struct to "struct nshhdr" to match the usual pattern. Removed packet type defines, these are now shared with VXLAN-GPE.] Signed-off-by: Yi Yang <[email protected]> Signed-off-by: Jiri Benc <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fa20e0e commit 1f0b774

File tree

1 file changed

+307
-0
lines changed

1 file changed

+307
-0
lines changed

include/net/nsh.h

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
#ifndef __NET_NSH_H
2+
#define __NET_NSH_H 1
3+
4+
#include <linux/skbuff.h>
5+
6+
/*
7+
* Network Service Header:
8+
* 0 1 2 3
9+
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
10+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11+
* |Ver|O|U| TTL | Length |U|U|U|U|MD Type| Next Protocol |
12+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13+
* | Service Path Identifier (SPI) | Service Index |
14+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15+
* | |
16+
* ~ Mandatory/Optional Context Headers ~
17+
* | |
18+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19+
*
20+
* Version: The version field is used to ensure backward compatibility
21+
* going forward with future NSH specification updates. It MUST be set
22+
* to 0x0 by the sender, in this first revision of NSH. Given the
23+
* widespread implementation of existing hardware that uses the first
24+
* nibble after an MPLS label stack for ECMP decision processing, this
25+
* document reserves version 01b and this value MUST NOT be used in
26+
* future versions of the protocol. Please see [RFC7325] for further
27+
* discussion of MPLS-related forwarding requirements.
28+
*
29+
* O bit: Setting this bit indicates an Operations, Administration, and
30+
* Maintenance (OAM) packet. The actual format and processing of SFC
31+
* OAM packets is outside the scope of this specification (see for
32+
* example [I-D.ietf-sfc-oam-framework] for one approach).
33+
*
34+
* The O bit MUST be set for OAM packets and MUST NOT be set for non-OAM
35+
* packets. The O bit MUST NOT be modified along the SFP.
36+
*
37+
* SF/SFF/SFC Proxy/Classifier implementations that do not support SFC
38+
* OAM procedures SHOULD discard packets with O bit set, but MAY support
39+
* a configurable parameter to enable forwarding received SFC OAM
40+
* packets unmodified to the next element in the chain. Forwarding OAM
41+
* packets unmodified by SFC elements that do not support SFC OAM
42+
* procedures may be acceptable for a subset of OAM functions, but can
43+
* result in unexpected outcomes for others, thus it is recommended to
44+
* analyze the impact of forwarding an OAM packet for all OAM functions
45+
* prior to enabling this behavior. The configurable parameter MUST be
46+
* disabled by default.
47+
*
48+
* TTL: Indicates the maximum SFF hops for an SFP. This field is used
49+
* for service plane loop detection. The initial TTL value SHOULD be
50+
* configurable via the control plane; the configured initial value can
51+
* be specific to one or more SFPs. If no initial value is explicitly
52+
* provided, the default initial TTL value of 63 MUST be used. Each SFF
53+
* involved in forwarding an NSH packet MUST decrement the TTL value by
54+
* 1 prior to NSH forwarding lookup. Decrementing by 1 from an incoming
55+
* value of 0 shall result in a TTL value of 63. The packet MUST NOT be
56+
* forwarded if TTL is, after decrement, 0.
57+
*
58+
* All other flag fields, marked U, are unassigned and available for
59+
* future use, see Section 11.2.1. Unassigned bits MUST be set to zero
60+
* upon origination, and MUST be ignored and preserved unmodified by
61+
* other NSH supporting elements. Elements which do not understand the
62+
* meaning of any of these bits MUST NOT modify their actions based on
63+
* those unknown bits.
64+
*
65+
* Length: The total length, in 4-byte words, of NSH including the Base
66+
* Header, the Service Path Header, the Fixed Length Context Header or
67+
* Variable Length Context Header(s). The length MUST be 0x6 for MD
68+
* Type equal to 0x1, and MUST be 0x2 or greater for MD Type equal to
69+
* 0x2. The length of the NSH header MUST be an integer multiple of 4
70+
* bytes, thus variable length metadata is always padded out to a
71+
* multiple of 4 bytes.
72+
*
73+
* MD Type: Indicates the format of NSH beyond the mandatory Base Header
74+
* and the Service Path Header. MD Type defines the format of the
75+
* metadata being carried.
76+
*
77+
* 0x0 - This is a reserved value. Implementations SHOULD silently
78+
* discard packets with MD Type 0x0.
79+
*
80+
* 0x1 - This indicates that the format of the header includes a fixed
81+
* length Context Header (see Figure 4 below).
82+
*
83+
* 0x2 - This does not mandate any headers beyond the Base Header and
84+
* Service Path Header, but may contain optional variable length Context
85+
* Header(s). The semantics of the variable length Context Header(s)
86+
* are not defined in this document. The format of the optional
87+
* variable length Context Headers is provided in Section 2.5.1.
88+
*
89+
* 0xF - This value is reserved for experimentation and testing, as per
90+
* [RFC3692]. Implementations not explicitly configured to be part of
91+
* an experiment SHOULD silently discard packets with MD Type 0xF.
92+
*
93+
* Next Protocol: indicates the protocol type of the encapsulated data.
94+
* NSH does not alter the inner payload, and the semantics on the inner
95+
* protocol remain unchanged due to NSH service function chaining.
96+
* Please see the IANA Considerations section below, Section 11.2.5.
97+
*
98+
* This document defines the following Next Protocol values:
99+
*
100+
* 0x1: IPv4
101+
* 0x2: IPv6
102+
* 0x3: Ethernet
103+
* 0x4: NSH
104+
* 0x5: MPLS
105+
* 0xFE: Experiment 1
106+
* 0xFF: Experiment 2
107+
*
108+
* Packets with Next Protocol values not supported SHOULD be silently
109+
* dropped by default, although an implementation MAY provide a
110+
* configuration parameter to forward them. Additionally, an
111+
* implementation not explicitly configured for a specific experiment
112+
* [RFC3692] SHOULD silently drop packets with Next Protocol values 0xFE
113+
* and 0xFF.
114+
*
115+
* Service Path Identifier (SPI): Identifies a service path.
116+
* Participating nodes MUST use this identifier for Service Function
117+
* Path selection. The initial classifier MUST set the appropriate SPI
118+
* for a given classification result.
119+
*
120+
* Service Index (SI): Provides location within the SFP. The initial
121+
* classifier for a given SFP SHOULD set the SI to 255, however the
122+
* control plane MAY configure the initial value of SI as appropriate
123+
* (i.e., taking into account the length of the service function path).
124+
* The Service Index MUST be decremented by a value of 1 by Service
125+
* Functions or by SFC Proxy nodes after performing required services
126+
* and the new decremented SI value MUST be used in the egress packet's
127+
* NSH. The initial Classifier MUST send the packet to the first SFF in
128+
* the identified SFP for forwarding along an SFP. If re-classification
129+
* occurs, and that re-classification results in a new SPI, the
130+
* (re)classifier is, in effect, the initial classifier for the
131+
* resultant SPI.
132+
*
133+
* The SI is used in conjunction the with Service Path Identifier for
134+
* Service Function Path Selection and for determining the next SFF/SF
135+
* in the path. The SI is also valuable when troubleshooting or
136+
* reporting service paths. Additionally, while the TTL field is the
137+
* main mechanism for service plane loop detection, the SI can also be
138+
* used for detecting service plane loops.
139+
*
140+
* When the Base Header specifies MD Type = 0x1, a Fixed Length Context
141+
* Header (16-bytes) MUST be present immediately following the Service
142+
* Path Header. The value of a Fixed Length Context
143+
* Header that carries no metadata MUST be set to zero.
144+
*
145+
* When the base header specifies MD Type = 0x2, zero or more Variable
146+
* Length Context Headers MAY be added, immediately following the
147+
* Service Path Header (see Figure 5). Therefore, Length = 0x2,
148+
* indicates that only the Base Header followed by the Service Path
149+
* Header are present. The optional Variable Length Context Headers
150+
* MUST be of an integer number of 4-bytes. The base header Length
151+
* field MUST be used to determine the offset to locate the original
152+
* packet or frame for SFC nodes that require access to that
153+
* information.
154+
*
155+
* The format of the optional variable length Context Headers
156+
*
157+
* 0 1 2 3
158+
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
159+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160+
* | Metadata Class | Type |U| Length |
161+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162+
* | Variable Metadata |
163+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164+
*
165+
* Metadata Class (MD Class): Defines the scope of the 'Type' field to
166+
* provide a hierarchical namespace. The IANA Considerations
167+
* Section 11.2.4 defines how the MD Class values can be allocated to
168+
* standards bodies, vendors, and others.
169+
*
170+
* Type: Indicates the explicit type of metadata being carried. The
171+
* definition of the Type is the responsibility of the MD Class owner.
172+
*
173+
* Unassigned bit: One unassigned bit is available for future use. This
174+
* bit MUST NOT be set, and MUST be ignored on receipt.
175+
*
176+
* Length: Indicates the length of the variable metadata, in bytes. In
177+
* case the metadata length is not an integer number of 4-byte words,
178+
* the sender MUST add pad bytes immediately following the last metadata
179+
* byte to extend the metadata to an integer number of 4-byte words.
180+
* The receiver MUST round up the length field to the nearest 4-byte
181+
* word boundary, to locate and process the next field in the packet.
182+
* The receiver MUST access only those bytes in the metadata indicated
183+
* by the length field (i.e., actual number of bytes) and MUST ignore
184+
* the remaining bytes up to the nearest 4-byte word boundary. The
185+
* Length may be 0 or greater.
186+
*
187+
* A value of 0 denotes a Context Header without a Variable Metadata
188+
* field.
189+
*
190+
* [0] https://datatracker.ietf.org/doc/draft-ietf-sfc-nsh/
191+
*/
192+
193+
/**
194+
* struct nsh_md1_ctx - Keeps track of NSH context data
195+
* @nshc<1-4>: NSH Contexts.
196+
*/
197+
struct nsh_md1_ctx {
198+
__be32 context[4];
199+
};
200+
201+
struct nsh_md2_tlv {
202+
__be16 md_class;
203+
u8 type;
204+
u8 length;
205+
u8 md_value[];
206+
};
207+
208+
struct nshhdr {
209+
__be16 ver_flags_ttl_len;
210+
u8 mdtype;
211+
u8 np;
212+
__be32 path_hdr;
213+
union {
214+
struct nsh_md1_ctx md1;
215+
struct nsh_md2_tlv md2;
216+
};
217+
};
218+
219+
/* Masking NSH header fields. */
220+
#define NSH_VER_MASK 0xc000
221+
#define NSH_VER_SHIFT 14
222+
#define NSH_FLAGS_MASK 0x3000
223+
#define NSH_FLAGS_SHIFT 12
224+
#define NSH_TTL_MASK 0x0fc0
225+
#define NSH_TTL_SHIFT 6
226+
#define NSH_LEN_MASK 0x003f
227+
#define NSH_LEN_SHIFT 0
228+
229+
#define NSH_MDTYPE_MASK 0x0f
230+
#define NSH_MDTYPE_SHIFT 0
231+
232+
#define NSH_SPI_MASK 0xffffff00
233+
#define NSH_SPI_SHIFT 8
234+
#define NSH_SI_MASK 0x000000ff
235+
#define NSH_SI_SHIFT 0
236+
237+
/* MD Type Registry. */
238+
#define NSH_M_TYPE1 0x01
239+
#define NSH_M_TYPE2 0x02
240+
#define NSH_M_EXP1 0xFE
241+
#define NSH_M_EXP2 0xFF
242+
243+
/* NSH Base Header Length */
244+
#define NSH_BASE_HDR_LEN 8
245+
246+
/* NSH MD Type 1 header Length. */
247+
#define NSH_M_TYPE1_LEN 24
248+
249+
/* NSH header maximum Length. */
250+
#define NSH_HDR_MAX_LEN 256
251+
252+
/* NSH context headers maximum Length. */
253+
#define NSH_CTX_HDRS_MAX_LEN 248
254+
255+
static inline struct nshhdr *nsh_hdr(struct sk_buff *skb)
256+
{
257+
return (struct nshhdr *)skb_network_header(skb);
258+
}
259+
260+
static inline u16 nsh_hdr_len(const struct nshhdr *nsh)
261+
{
262+
return ((ntohs(nsh->ver_flags_ttl_len) & NSH_LEN_MASK)
263+
>> NSH_LEN_SHIFT) << 2;
264+
}
265+
266+
static inline u8 nsh_get_ver(const struct nshhdr *nsh)
267+
{
268+
return (ntohs(nsh->ver_flags_ttl_len) & NSH_VER_MASK)
269+
>> NSH_VER_SHIFT;
270+
}
271+
272+
static inline u8 nsh_get_flags(const struct nshhdr *nsh)
273+
{
274+
return (ntohs(nsh->ver_flags_ttl_len) & NSH_FLAGS_MASK)
275+
>> NSH_FLAGS_SHIFT;
276+
}
277+
278+
static inline u8 nsh_get_ttl(const struct nshhdr *nsh)
279+
{
280+
return (ntohs(nsh->ver_flags_ttl_len) & NSH_TTL_MASK)
281+
>> NSH_TTL_SHIFT;
282+
}
283+
284+
static inline void __nsh_set_xflag(struct nshhdr *nsh, u16 xflag, u16 xmask)
285+
{
286+
nsh->ver_flags_ttl_len
287+
= (nsh->ver_flags_ttl_len & ~htons(xmask)) | htons(xflag);
288+
}
289+
290+
static inline void nsh_set_flags_and_ttl(struct nshhdr *nsh, u8 flags, u8 ttl)
291+
{
292+
__nsh_set_xflag(nsh, ((flags << NSH_FLAGS_SHIFT) & NSH_FLAGS_MASK) |
293+
((ttl << NSH_TTL_SHIFT) & NSH_TTL_MASK),
294+
NSH_FLAGS_MASK | NSH_TTL_MASK);
295+
}
296+
297+
static inline void nsh_set_flags_ttl_len(struct nshhdr *nsh, u8 flags,
298+
u8 ttl, u8 len)
299+
{
300+
len = len >> 2;
301+
__nsh_set_xflag(nsh, ((flags << NSH_FLAGS_SHIFT) & NSH_FLAGS_MASK) |
302+
((ttl << NSH_TTL_SHIFT) & NSH_TTL_MASK) |
303+
((len << NSH_LEN_SHIFT) & NSH_LEN_MASK),
304+
NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK);
305+
}
306+
307+
#endif /* __NET_NSH_H */

0 commit comments

Comments
 (0)