162306a36Sopenharmony_ci#ifndef __NET_NSH_H 262306a36Sopenharmony_ci#define __NET_NSH_H 1 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/skbuff.h> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci/* 762306a36Sopenharmony_ci * Network Service Header: 862306a36Sopenharmony_ci * 0 1 2 3 962306a36Sopenharmony_ci * 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 1062306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1162306a36Sopenharmony_ci * |Ver|O|U| TTL | Length |U|U|U|U|MD Type| Next Protocol | 1262306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1362306a36Sopenharmony_ci * | Service Path Identifier (SPI) | Service Index | 1462306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1562306a36Sopenharmony_ci * | | 1662306a36Sopenharmony_ci * ~ Mandatory/Optional Context Headers ~ 1762306a36Sopenharmony_ci * | | 1862306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Version: The version field is used to ensure backward compatibility 2162306a36Sopenharmony_ci * going forward with future NSH specification updates. It MUST be set 2262306a36Sopenharmony_ci * to 0x0 by the sender, in this first revision of NSH. Given the 2362306a36Sopenharmony_ci * widespread implementation of existing hardware that uses the first 2462306a36Sopenharmony_ci * nibble after an MPLS label stack for ECMP decision processing, this 2562306a36Sopenharmony_ci * document reserves version 01b and this value MUST NOT be used in 2662306a36Sopenharmony_ci * future versions of the protocol. Please see [RFC7325] for further 2762306a36Sopenharmony_ci * discussion of MPLS-related forwarding requirements. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * O bit: Setting this bit indicates an Operations, Administration, and 3062306a36Sopenharmony_ci * Maintenance (OAM) packet. The actual format and processing of SFC 3162306a36Sopenharmony_ci * OAM packets is outside the scope of this specification (see for 3262306a36Sopenharmony_ci * example [I-D.ietf-sfc-oam-framework] for one approach). 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * The O bit MUST be set for OAM packets and MUST NOT be set for non-OAM 3562306a36Sopenharmony_ci * packets. The O bit MUST NOT be modified along the SFP. 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * SF/SFF/SFC Proxy/Classifier implementations that do not support SFC 3862306a36Sopenharmony_ci * OAM procedures SHOULD discard packets with O bit set, but MAY support 3962306a36Sopenharmony_ci * a configurable parameter to enable forwarding received SFC OAM 4062306a36Sopenharmony_ci * packets unmodified to the next element in the chain. Forwarding OAM 4162306a36Sopenharmony_ci * packets unmodified by SFC elements that do not support SFC OAM 4262306a36Sopenharmony_ci * procedures may be acceptable for a subset of OAM functions, but can 4362306a36Sopenharmony_ci * result in unexpected outcomes for others, thus it is recommended to 4462306a36Sopenharmony_ci * analyze the impact of forwarding an OAM packet for all OAM functions 4562306a36Sopenharmony_ci * prior to enabling this behavior. The configurable parameter MUST be 4662306a36Sopenharmony_ci * disabled by default. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * TTL: Indicates the maximum SFF hops for an SFP. This field is used 4962306a36Sopenharmony_ci * for service plane loop detection. The initial TTL value SHOULD be 5062306a36Sopenharmony_ci * configurable via the control plane; the configured initial value can 5162306a36Sopenharmony_ci * be specific to one or more SFPs. If no initial value is explicitly 5262306a36Sopenharmony_ci * provided, the default initial TTL value of 63 MUST be used. Each SFF 5362306a36Sopenharmony_ci * involved in forwarding an NSH packet MUST decrement the TTL value by 5462306a36Sopenharmony_ci * 1 prior to NSH forwarding lookup. Decrementing by 1 from an incoming 5562306a36Sopenharmony_ci * value of 0 shall result in a TTL value of 63. The packet MUST NOT be 5662306a36Sopenharmony_ci * forwarded if TTL is, after decrement, 0. 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * All other flag fields, marked U, are unassigned and available for 5962306a36Sopenharmony_ci * future use, see Section 11.2.1. Unassigned bits MUST be set to zero 6062306a36Sopenharmony_ci * upon origination, and MUST be ignored and preserved unmodified by 6162306a36Sopenharmony_ci * other NSH supporting elements. Elements which do not understand the 6262306a36Sopenharmony_ci * meaning of any of these bits MUST NOT modify their actions based on 6362306a36Sopenharmony_ci * those unknown bits. 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * Length: The total length, in 4-byte words, of NSH including the Base 6662306a36Sopenharmony_ci * Header, the Service Path Header, the Fixed Length Context Header or 6762306a36Sopenharmony_ci * Variable Length Context Header(s). The length MUST be 0x6 for MD 6862306a36Sopenharmony_ci * Type equal to 0x1, and MUST be 0x2 or greater for MD Type equal to 6962306a36Sopenharmony_ci * 0x2. The length of the NSH header MUST be an integer multiple of 4 7062306a36Sopenharmony_ci * bytes, thus variable length metadata is always padded out to a 7162306a36Sopenharmony_ci * multiple of 4 bytes. 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * MD Type: Indicates the format of NSH beyond the mandatory Base Header 7462306a36Sopenharmony_ci * and the Service Path Header. MD Type defines the format of the 7562306a36Sopenharmony_ci * metadata being carried. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * 0x0 - This is a reserved value. Implementations SHOULD silently 7862306a36Sopenharmony_ci * discard packets with MD Type 0x0. 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci * 0x1 - This indicates that the format of the header includes a fixed 8162306a36Sopenharmony_ci * length Context Header (see Figure 4 below). 8262306a36Sopenharmony_ci * 8362306a36Sopenharmony_ci * 0x2 - This does not mandate any headers beyond the Base Header and 8462306a36Sopenharmony_ci * Service Path Header, but may contain optional variable length Context 8562306a36Sopenharmony_ci * Header(s). The semantics of the variable length Context Header(s) 8662306a36Sopenharmony_ci * are not defined in this document. The format of the optional 8762306a36Sopenharmony_ci * variable length Context Headers is provided in Section 2.5.1. 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * 0xF - This value is reserved for experimentation and testing, as per 9062306a36Sopenharmony_ci * [RFC3692]. Implementations not explicitly configured to be part of 9162306a36Sopenharmony_ci * an experiment SHOULD silently discard packets with MD Type 0xF. 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci * Next Protocol: indicates the protocol type of the encapsulated data. 9462306a36Sopenharmony_ci * NSH does not alter the inner payload, and the semantics on the inner 9562306a36Sopenharmony_ci * protocol remain unchanged due to NSH service function chaining. 9662306a36Sopenharmony_ci * Please see the IANA Considerations section below, Section 11.2.5. 9762306a36Sopenharmony_ci * 9862306a36Sopenharmony_ci * This document defines the following Next Protocol values: 9962306a36Sopenharmony_ci * 10062306a36Sopenharmony_ci * 0x1: IPv4 10162306a36Sopenharmony_ci * 0x2: IPv6 10262306a36Sopenharmony_ci * 0x3: Ethernet 10362306a36Sopenharmony_ci * 0x4: NSH 10462306a36Sopenharmony_ci * 0x5: MPLS 10562306a36Sopenharmony_ci * 0xFE: Experiment 1 10662306a36Sopenharmony_ci * 0xFF: Experiment 2 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * Packets with Next Protocol values not supported SHOULD be silently 10962306a36Sopenharmony_ci * dropped by default, although an implementation MAY provide a 11062306a36Sopenharmony_ci * configuration parameter to forward them. Additionally, an 11162306a36Sopenharmony_ci * implementation not explicitly configured for a specific experiment 11262306a36Sopenharmony_ci * [RFC3692] SHOULD silently drop packets with Next Protocol values 0xFE 11362306a36Sopenharmony_ci * and 0xFF. 11462306a36Sopenharmony_ci * 11562306a36Sopenharmony_ci * Service Path Identifier (SPI): Identifies a service path. 11662306a36Sopenharmony_ci * Participating nodes MUST use this identifier for Service Function 11762306a36Sopenharmony_ci * Path selection. The initial classifier MUST set the appropriate SPI 11862306a36Sopenharmony_ci * for a given classification result. 11962306a36Sopenharmony_ci * 12062306a36Sopenharmony_ci * Service Index (SI): Provides location within the SFP. The initial 12162306a36Sopenharmony_ci * classifier for a given SFP SHOULD set the SI to 255, however the 12262306a36Sopenharmony_ci * control plane MAY configure the initial value of SI as appropriate 12362306a36Sopenharmony_ci * (i.e., taking into account the length of the service function path). 12462306a36Sopenharmony_ci * The Service Index MUST be decremented by a value of 1 by Service 12562306a36Sopenharmony_ci * Functions or by SFC Proxy nodes after performing required services 12662306a36Sopenharmony_ci * and the new decremented SI value MUST be used in the egress packet's 12762306a36Sopenharmony_ci * NSH. The initial Classifier MUST send the packet to the first SFF in 12862306a36Sopenharmony_ci * the identified SFP for forwarding along an SFP. If re-classification 12962306a36Sopenharmony_ci * occurs, and that re-classification results in a new SPI, the 13062306a36Sopenharmony_ci * (re)classifier is, in effect, the initial classifier for the 13162306a36Sopenharmony_ci * resultant SPI. 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci * The SI is used in conjunction the with Service Path Identifier for 13462306a36Sopenharmony_ci * Service Function Path Selection and for determining the next SFF/SF 13562306a36Sopenharmony_ci * in the path. The SI is also valuable when troubleshooting or 13662306a36Sopenharmony_ci * reporting service paths. Additionally, while the TTL field is the 13762306a36Sopenharmony_ci * main mechanism for service plane loop detection, the SI can also be 13862306a36Sopenharmony_ci * used for detecting service plane loops. 13962306a36Sopenharmony_ci * 14062306a36Sopenharmony_ci * When the Base Header specifies MD Type = 0x1, a Fixed Length Context 14162306a36Sopenharmony_ci * Header (16-bytes) MUST be present immediately following the Service 14262306a36Sopenharmony_ci * Path Header. The value of a Fixed Length Context 14362306a36Sopenharmony_ci * Header that carries no metadata MUST be set to zero. 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * When the base header specifies MD Type = 0x2, zero or more Variable 14662306a36Sopenharmony_ci * Length Context Headers MAY be added, immediately following the 14762306a36Sopenharmony_ci * Service Path Header (see Figure 5). Therefore, Length = 0x2, 14862306a36Sopenharmony_ci * indicates that only the Base Header followed by the Service Path 14962306a36Sopenharmony_ci * Header are present. The optional Variable Length Context Headers 15062306a36Sopenharmony_ci * MUST be of an integer number of 4-bytes. The base header Length 15162306a36Sopenharmony_ci * field MUST be used to determine the offset to locate the original 15262306a36Sopenharmony_ci * packet or frame for SFC nodes that require access to that 15362306a36Sopenharmony_ci * information. 15462306a36Sopenharmony_ci * 15562306a36Sopenharmony_ci * The format of the optional variable length Context Headers 15662306a36Sopenharmony_ci * 15762306a36Sopenharmony_ci * 0 1 2 3 15862306a36Sopenharmony_ci * 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 15962306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16062306a36Sopenharmony_ci * | Metadata Class | Type |U| Length | 16162306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16262306a36Sopenharmony_ci * | Variable Metadata | 16362306a36Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * Metadata Class (MD Class): Defines the scope of the 'Type' field to 16662306a36Sopenharmony_ci * provide a hierarchical namespace. The IANA Considerations 16762306a36Sopenharmony_ci * Section 11.2.4 defines how the MD Class values can be allocated to 16862306a36Sopenharmony_ci * standards bodies, vendors, and others. 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci * Type: Indicates the explicit type of metadata being carried. The 17162306a36Sopenharmony_ci * definition of the Type is the responsibility of the MD Class owner. 17262306a36Sopenharmony_ci * 17362306a36Sopenharmony_ci * Unassigned bit: One unassigned bit is available for future use. This 17462306a36Sopenharmony_ci * bit MUST NOT be set, and MUST be ignored on receipt. 17562306a36Sopenharmony_ci * 17662306a36Sopenharmony_ci * Length: Indicates the length of the variable metadata, in bytes. In 17762306a36Sopenharmony_ci * case the metadata length is not an integer number of 4-byte words, 17862306a36Sopenharmony_ci * the sender MUST add pad bytes immediately following the last metadata 17962306a36Sopenharmony_ci * byte to extend the metadata to an integer number of 4-byte words. 18062306a36Sopenharmony_ci * The receiver MUST round up the length field to the nearest 4-byte 18162306a36Sopenharmony_ci * word boundary, to locate and process the next field in the packet. 18262306a36Sopenharmony_ci * The receiver MUST access only those bytes in the metadata indicated 18362306a36Sopenharmony_ci * by the length field (i.e., actual number of bytes) and MUST ignore 18462306a36Sopenharmony_ci * the remaining bytes up to the nearest 4-byte word boundary. The 18562306a36Sopenharmony_ci * Length may be 0 or greater. 18662306a36Sopenharmony_ci * 18762306a36Sopenharmony_ci * A value of 0 denotes a Context Header without a Variable Metadata 18862306a36Sopenharmony_ci * field. 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * [0] https://datatracker.ietf.org/doc/draft-ietf-sfc-nsh/ 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/** 19462306a36Sopenharmony_ci * struct nsh_md1_ctx - Keeps track of NSH context data 19562306a36Sopenharmony_ci * @context: NSH Contexts. 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_cistruct nsh_md1_ctx { 19862306a36Sopenharmony_ci __be32 context[4]; 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistruct nsh_md2_tlv { 20262306a36Sopenharmony_ci __be16 md_class; 20362306a36Sopenharmony_ci u8 type; 20462306a36Sopenharmony_ci u8 length; 20562306a36Sopenharmony_ci u8 md_value[]; 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistruct nshhdr { 20962306a36Sopenharmony_ci __be16 ver_flags_ttl_len; 21062306a36Sopenharmony_ci u8 mdtype; 21162306a36Sopenharmony_ci u8 np; 21262306a36Sopenharmony_ci __be32 path_hdr; 21362306a36Sopenharmony_ci union { 21462306a36Sopenharmony_ci struct nsh_md1_ctx md1; 21562306a36Sopenharmony_ci struct nsh_md2_tlv md2; 21662306a36Sopenharmony_ci }; 21762306a36Sopenharmony_ci}; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/* Masking NSH header fields. */ 22062306a36Sopenharmony_ci#define NSH_VER_MASK 0xc000 22162306a36Sopenharmony_ci#define NSH_VER_SHIFT 14 22262306a36Sopenharmony_ci#define NSH_FLAGS_MASK 0x3000 22362306a36Sopenharmony_ci#define NSH_FLAGS_SHIFT 12 22462306a36Sopenharmony_ci#define NSH_TTL_MASK 0x0fc0 22562306a36Sopenharmony_ci#define NSH_TTL_SHIFT 6 22662306a36Sopenharmony_ci#define NSH_LEN_MASK 0x003f 22762306a36Sopenharmony_ci#define NSH_LEN_SHIFT 0 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci#define NSH_MDTYPE_MASK 0x0f 23062306a36Sopenharmony_ci#define NSH_MDTYPE_SHIFT 0 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#define NSH_SPI_MASK 0xffffff00 23362306a36Sopenharmony_ci#define NSH_SPI_SHIFT 8 23462306a36Sopenharmony_ci#define NSH_SI_MASK 0x000000ff 23562306a36Sopenharmony_ci#define NSH_SI_SHIFT 0 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/* MD Type Registry. */ 23862306a36Sopenharmony_ci#define NSH_M_TYPE1 0x01 23962306a36Sopenharmony_ci#define NSH_M_TYPE2 0x02 24062306a36Sopenharmony_ci#define NSH_M_EXP1 0xFE 24162306a36Sopenharmony_ci#define NSH_M_EXP2 0xFF 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/* NSH Base Header Length */ 24462306a36Sopenharmony_ci#define NSH_BASE_HDR_LEN 8 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* NSH MD Type 1 header Length. */ 24762306a36Sopenharmony_ci#define NSH_M_TYPE1_LEN 24 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/* NSH header maximum Length. */ 25062306a36Sopenharmony_ci#define NSH_HDR_MAX_LEN 256 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/* NSH context headers maximum Length. */ 25362306a36Sopenharmony_ci#define NSH_CTX_HDRS_MAX_LEN 248 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic inline struct nshhdr *nsh_hdr(struct sk_buff *skb) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci return (struct nshhdr *)skb_network_header(skb); 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic inline u16 nsh_hdr_len(const struct nshhdr *nsh) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci return ((ntohs(nsh->ver_flags_ttl_len) & NSH_LEN_MASK) 26362306a36Sopenharmony_ci >> NSH_LEN_SHIFT) << 2; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic inline u8 nsh_get_ver(const struct nshhdr *nsh) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci return (ntohs(nsh->ver_flags_ttl_len) & NSH_VER_MASK) 26962306a36Sopenharmony_ci >> NSH_VER_SHIFT; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic inline u8 nsh_get_flags(const struct nshhdr *nsh) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci return (ntohs(nsh->ver_flags_ttl_len) & NSH_FLAGS_MASK) 27562306a36Sopenharmony_ci >> NSH_FLAGS_SHIFT; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic inline u8 nsh_get_ttl(const struct nshhdr *nsh) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci return (ntohs(nsh->ver_flags_ttl_len) & NSH_TTL_MASK) 28162306a36Sopenharmony_ci >> NSH_TTL_SHIFT; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic inline void __nsh_set_xflag(struct nshhdr *nsh, u16 xflag, u16 xmask) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci nsh->ver_flags_ttl_len 28762306a36Sopenharmony_ci = (nsh->ver_flags_ttl_len & ~htons(xmask)) | htons(xflag); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic inline void nsh_set_flags_and_ttl(struct nshhdr *nsh, u8 flags, u8 ttl) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci __nsh_set_xflag(nsh, ((flags << NSH_FLAGS_SHIFT) & NSH_FLAGS_MASK) | 29362306a36Sopenharmony_ci ((ttl << NSH_TTL_SHIFT) & NSH_TTL_MASK), 29462306a36Sopenharmony_ci NSH_FLAGS_MASK | NSH_TTL_MASK); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic inline void nsh_set_flags_ttl_len(struct nshhdr *nsh, u8 flags, 29862306a36Sopenharmony_ci u8 ttl, u8 len) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci len = len >> 2; 30162306a36Sopenharmony_ci __nsh_set_xflag(nsh, ((flags << NSH_FLAGS_SHIFT) & NSH_FLAGS_MASK) | 30262306a36Sopenharmony_ci ((ttl << NSH_TTL_SHIFT) & NSH_TTL_MASK) | 30362306a36Sopenharmony_ci ((len << NSH_LEN_SHIFT) & NSH_LEN_MASK), 30462306a36Sopenharmony_ci NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK); 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ciint nsh_push(struct sk_buff *skb, const struct nshhdr *pushed_nh); 30862306a36Sopenharmony_ciint nsh_pop(struct sk_buff *skb); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci#endif /* __NET_NSH_H */ 311