Commit | Line | Data |
---|---|---|
1f0b7744 YY |
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 | ||
b2d0f5d5 YY |
307 | int nsh_push(struct sk_buff *skb, const struct nshhdr *pushed_nh); |
308 | int nsh_pop(struct sk_buff *skb); | |
309 | ||
1f0b7744 | 310 | #endif /* __NET_NSH_H */ |