|
| 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