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
nsh_hdr(struct sk_buff * skb)255 static inline struct nshhdr *nsh_hdr(struct sk_buff *skb)
256 {
257 return (struct nshhdr *)skb_network_header(skb);
258 }
259
nsh_hdr_len(const struct nshhdr * nsh)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
nsh_get_ver(const struct nshhdr * nsh)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
nsh_get_flags(const struct nshhdr * nsh)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
nsh_get_ttl(const struct nshhdr * nsh)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
__nsh_set_xflag(struct nshhdr * nsh,u16 xflag,u16 xmask)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
nsh_set_flags_and_ttl(struct nshhdr * nsh,u8 flags,u8 ttl)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
nsh_set_flags_ttl_len(struct nshhdr * nsh,u8 flags,u8 ttl,u8 len)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 int nsh_push(struct sk_buff *skb, const struct nshhdr *pushed_nh);
308 int nsh_pop(struct sk_buff *skb);
309
310 #endif /* __NET_NSH_H */
311