| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 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 | 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 */ |