Chenmin Sun | 7f83738 | 2020-03-28 00:34:19 +0800 | [diff] [blame] | 1 | From e9e33a31aa58293c0442ddbfb96f3b8badfad250 Mon Sep 17 00:00:00 2001 |
| 2 | From: Qi Zhang <qi.z.zhang@intel.com> |
| 3 | Date: Thu, 9 Apr 2020 13:10:12 +0800 |
| 4 | Subject: [DPDK 06/17] common/iavf: add virtual channel protocol header |
| 5 | |
| 6 | To support advanced AVF's FDIR and RSS feature, we need to figure out |
| 7 | what kind of data structure should be passed from VF to PF to describe |
| 8 | an FDIR rule or RSS config rule. The common part of the requirement is |
| 9 | we need a data structure to represent the input set selection of a rule's |
| 10 | hash key. |
| 11 | |
| 12 | An input set selection is a group of fields be selected from one or more |
| 13 | network protocol layers that could be identified as a specific flow. |
| 14 | For example, select dst IP address from an IPv4 header combined with |
| 15 | dst port from the TCP header as the input set for an IPv4/TCP flow. |
| 16 | |
| 17 | The patch adds a new data structure virtchnl_proto_hdrs to abstract |
| 18 | a network protocol headers group which is composed of layers of network |
| 19 | protocol header(virtchnl_proto_hdr). |
| 20 | |
| 21 | A protocol header contains a 32 bits mask (field_selector) to describe |
| 22 | which fields are selected as input sets, as well as a header type |
| 23 | (enum virtchnl_proto_hdr_type). Each bit is mapped to a field in |
| 24 | enum virtchnl_proto_hdr_field guided by its header type. |
| 25 | |
| 26 | +------------+-----------+------------------------------+ |
| 27 | | | Proto Hdr | Header Type A | |
| 28 | | | +------------------------------+ |
| 29 | | | | BIT 31 | ... | BIT 1 | BIT 0 | |
| 30 | | |-----------+------------------------------+ |
| 31 | |Proto Hdrs | Proto Hdr | Header Type B | |
| 32 | | | +------------------------------+ |
| 33 | | | | BIT 31 | ... | BIT 1 | BIT 0 | |
| 34 | | |-----------+------------------------------+ |
| 35 | | | Proto Hdr | Header Type C | |
| 36 | | | +------------------------------+ |
| 37 | | | | BIT 31 | ... | BIT 1 | BIT 0 | |
| 38 | | |-----------+------------------------------+ |
| 39 | | | .... | |
| 40 | +-------------------------------------------------------+ |
| 41 | |
| 42 | All fields in enum virtchnl_proto_hdr_fields are grouped with header type |
| 43 | and the value of the first field of a header type is always 32 aligned. |
| 44 | |
| 45 | enum proto_hdr_type { |
| 46 | header_type_A = 0; |
| 47 | header_type_B = 1; |
| 48 | .... |
| 49 | } |
| 50 | |
| 51 | enum proto_hdr_field { |
| 52 | /* header type A */ |
| 53 | header_A_field_0 = 0, |
| 54 | header_A_field_1 = 1, |
| 55 | header_A_field_2 = 2, |
| 56 | header_A_field_3 = 3, |
| 57 | |
| 58 | /* header type B */ |
| 59 | header_B_field_0 = 32, // = header_type_B << 5 |
| 60 | header_B_field_0 = 33, |
| 61 | header_B_field_0 = 34 |
| 62 | header_B_field_0 = 35, |
| 63 | .... |
| 64 | }; |
| 65 | |
| 66 | So we have: |
| 67 | proto_hdr_type = proto_hdr_field / 32 |
| 68 | bit offset = proto_hdr_field % 32 |
| 69 | |
| 70 | To simply the protocol header's operations, couple help macros are added. |
| 71 | For example, to select src IP and dst port as input set for an IPv4/UDP |
| 72 | flow. |
| 73 | |
| 74 | we have: |
| 75 | struct virtchnl_proto_hdr hdr[2]; |
| 76 | |
| 77 | VIRTCHNL_SET_PROTO_HDR_TYPE(&hdr[0], IPV4) |
| 78 | VIRTCHNL_ADD_PROTO_HDR_FIELD(&hdr[0], IPV4, SRC) |
| 79 | |
| 80 | VIRTCHNL_SET_PROTO_HDR_TYPE(&hdr[1], UDP) |
| 81 | VIRTCHNL_ADD_PROTO_HDR_FIELD(&hdr[1], UDP, DST) |
| 82 | |
| 83 | A protocol header also contains a byte array, this field should only |
| 84 | be used by an FDIR rule and should be ignored by RSS. For an FDIR rule, |
| 85 | the byte array is used to store the protocol header of a training |
| 86 | package. The byte array must be network order. |
| 87 | |
| 88 | Signed-off-by: Jeff Guo <jia.guo@intel.com> |
| 89 | Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com> |
| 90 | Signed-off-by: Qi Zhang <qi.z.zhang@intel.com> |
| 91 | --- |
| 92 | drivers/common/iavf/virtchnl.h | 156 +++++++++++++++++++++++++++++++++ |
| 93 | 1 file changed, 156 insertions(+) |
| 94 | |
| 95 | diff --git a/drivers/common/iavf/virtchnl.h b/drivers/common/iavf/virtchnl.h |
| 96 | index e8d936843..667762643 100644 |
| 97 | --- a/drivers/common/iavf/virtchnl.h |
| 98 | +++ b/drivers/common/iavf/virtchnl.h |
| 99 | @@ -769,6 +769,162 @@ enum virtchnl_vfr_states { |
| 100 | VIRTCHNL_VFR_VFACTIVE, |
| 101 | }; |
| 102 | |
| 103 | +#define VIRTCHNL_MAX_NUM_PROTO_HDRS 32 |
| 104 | +#define PROTO_HDR_SHIFT 5 |
| 105 | +#define PROTO_HDR_FIELD_START(proto_hdr_type) \ |
| 106 | + (proto_hdr_type << PROTO_HDR_SHIFT) |
| 107 | +#define PROTO_HDR_FIELD_MASK ((1UL << PROTO_HDR_SHIFT) - 1) |
| 108 | + |
| 109 | +/* VF use these macros to configure each protocol header. |
| 110 | + * Specify which protocol headers and protocol header fields base on |
| 111 | + * virtchnl_proto_hdr_type and virtchnl_proto_hdr_field. |
| 112 | + * @param hdr: a struct of virtchnl_proto_hdr |
| 113 | + * @param hdr_type: ETH/IPV4/TCP, etc |
| 114 | + * @param field: SRC/DST/TEID/SPI, etc |
| 115 | + */ |
| 116 | +#define VIRTCHNL_ADD_PROTO_HDR_FIELD(hdr, field) \ |
| 117 | + ((hdr)->field_selector |= BIT((field) & PROTO_HDR_FIELD_MASK)) |
| 118 | +#define VIRTCHNL_DEL_PROTO_HDR_FIELD(hdr, field) \ |
| 119 | + ((hdr)->field_selector &= ~BIT((field) & PROTO_HDR_FIELD_MASK)) |
| 120 | +#define VIRTCHNL_TEST_PROTO_HDR_FIELD(hdr, val) \ |
| 121 | + ((hdr)->field_selector & BIT((val) & PROTO_HDR_FIELD_MASK)) |
| 122 | +#define VIRTCHNL_GET_PROTO_HDR_FIELD(hdr) ((hdr)->field_selector) |
| 123 | + |
| 124 | +#define VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, hdr_type, field) \ |
| 125 | + (VIRTCHNL_ADD_PROTO_HDR_FIELD(hdr, \ |
| 126 | + VIRTCHNL_PROTO_HDR_ ## hdr_type ## _ ## field)) |
| 127 | +#define VIRTCHNL_DEL_PROTO_HDR_FIELD_BIT(hdr, hdr_type, field) \ |
| 128 | + (VIRTCHNL_DEL_PROTO_HDR_FIELD(hdr, \ |
| 129 | + VIRTCHNL_PROTO_HDR_ ## hdr_type ## _ ## field)) |
| 130 | + |
| 131 | +#define VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, hdr_type) \ |
| 132 | + ((hdr)->type = VIRTCHNL_PROTO_HDR_ ## hdr_type) |
| 133 | +#define VIRTCHNL_GET_PROTO_HDR_TYPE(hdr) \ |
| 134 | + (((hdr)->type) >> PROTO_HDR_SHIFT) |
| 135 | +#define VIRTCHNL_TEST_PROTO_HDR_TYPE(hdr, val) \ |
| 136 | + ((hdr)->type == ((val) >> PROTO_HDR_SHIFT)) |
| 137 | +#define VIRTCHNL_TEST_PROTO_HDR(hdr, val) \ |
| 138 | + (VIRTCHNL_TEST_PROTO_HDR_TYPE(hdr, val) && \ |
| 139 | + VIRTCHNL_TEST_PROTO_HDR_FIELD(hdr, val)) |
| 140 | + |
| 141 | +/* Protocol header type within a packet segment. A segment consists of one or |
| 142 | + * more protocol headers that make up a logical group of protocol headers. Each |
| 143 | + * logical group of protocol headers encapsulates or is encapsulated using/by |
| 144 | + * tunneling or encapsulation protocols for network virtualization. |
| 145 | + */ |
| 146 | +enum virtchnl_proto_hdr_type { |
| 147 | + VIRTCHNL_PROTO_HDR_NONE, |
| 148 | + VIRTCHNL_PROTO_HDR_ETH, |
| 149 | + VIRTCHNL_PROTO_HDR_S_VLAN, |
| 150 | + VIRTCHNL_PROTO_HDR_C_VLAN, |
| 151 | + VIRTCHNL_PROTO_HDR_IPV4, |
| 152 | + VIRTCHNL_PROTO_HDR_IPV6, |
| 153 | + VIRTCHNL_PROTO_HDR_TCP, |
| 154 | + VIRTCHNL_PROTO_HDR_UDP, |
| 155 | + VIRTCHNL_PROTO_HDR_SCTP, |
| 156 | + VIRTCHNL_PROTO_HDR_GTPU_IP, |
| 157 | + VIRTCHNL_PROTO_HDR_GTPU_EH, |
| 158 | + VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN, |
| 159 | + VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP, |
| 160 | + VIRTCHNL_PROTO_HDR_PPPOE, |
| 161 | + VIRTCHNL_PROTO_HDR_L2TPV3, |
| 162 | + VIRTCHNL_PROTO_HDR_ESP, |
| 163 | + VIRTCHNL_PROTO_HDR_AH, |
| 164 | + VIRTCHNL_PROTO_HDR_PFCP, |
| 165 | +}; |
| 166 | + |
| 167 | +/* Protocol header field within a protocol header. */ |
| 168 | +enum virtchnl_proto_hdr_field { |
| 169 | + /* ETHER */ |
| 170 | + VIRTCHNL_PROTO_HDR_ETH_SRC = |
| 171 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ETH), |
| 172 | + VIRTCHNL_PROTO_HDR_ETH_DST, |
| 173 | + VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE, |
| 174 | + /* S-VLAN */ |
| 175 | + VIRTCHNL_PROTO_HDR_S_VLAN_ID = |
| 176 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_S_VLAN), |
| 177 | + /* C-VLAN */ |
| 178 | + VIRTCHNL_PROTO_HDR_C_VLAN_ID = |
| 179 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_C_VLAN), |
| 180 | + /* IPV4 */ |
| 181 | + VIRTCHNL_PROTO_HDR_IPV4_SRC = |
| 182 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV4), |
| 183 | + VIRTCHNL_PROTO_HDR_IPV4_DST, |
| 184 | + VIRTCHNL_PROTO_HDR_IPV4_DSCP, |
| 185 | + VIRTCHNL_PROTO_HDR_IPV4_TTL, |
| 186 | + VIRTCHNL_PROTO_HDR_IPV4_PROT, |
| 187 | + /* IPV6 */ |
| 188 | + VIRTCHNL_PROTO_HDR_IPV6_SRC = |
| 189 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV6), |
| 190 | + VIRTCHNL_PROTO_HDR_IPV6_DST, |
| 191 | + VIRTCHNL_PROTO_HDR_IPV6_TC, |
| 192 | + VIRTCHNL_PROTO_HDR_IPV6_HOP_LIMIT, |
| 193 | + VIRTCHNL_PROTO_HDR_IPV6_PROT, |
| 194 | + /* TCP */ |
| 195 | + VIRTCHNL_PROTO_HDR_TCP_SRC_PORT = |
| 196 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_TCP), |
| 197 | + VIRTCHNL_PROTO_HDR_TCP_DST_PORT, |
| 198 | + /* UDP */ |
| 199 | + VIRTCHNL_PROTO_HDR_UDP_SRC_PORT = |
| 200 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_UDP), |
| 201 | + VIRTCHNL_PROTO_HDR_UDP_DST_PORT, |
| 202 | + /* SCTP */ |
| 203 | + VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT = |
| 204 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_SCTP), |
| 205 | + VIRTCHNL_PROTO_HDR_SCTP_DST_PORT, |
| 206 | + /* GTPU_IP */ |
| 207 | + VIRTCHNL_PROTO_HDR_GTPU_IP_TEID = |
| 208 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_IP), |
| 209 | + /* GTPU_EH */ |
| 210 | + VIRTCHNL_PROTO_HDR_GTPU_EH_PDU = |
| 211 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_EH), |
| 212 | + VIRTCHNL_PROTO_HDR_GTPU_EH_QFI, |
| 213 | + /* PPPOE */ |
| 214 | + VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID = |
| 215 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_PPPOE), |
| 216 | + /* L2TPV3 */ |
| 217 | + VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID = |
| 218 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_L2TPV3), |
| 219 | + /* ESP */ |
| 220 | + VIRTCHNL_PROTO_HDR_ESP_SPI = |
| 221 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ESP), |
| 222 | + /* AH */ |
| 223 | + VIRTCHNL_PROTO_HDR_AH_SPI = |
| 224 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_AH), |
| 225 | + /* PFCP */ |
| 226 | + VIRTCHNL_PROTO_HDR_PFCP_S_FIELD = |
| 227 | + PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_PFCP), |
| 228 | + VIRTCHNL_PROTO_HDR_PFCP_SEID, |
| 229 | +}; |
| 230 | + |
| 231 | +struct virtchnl_proto_hdr { |
| 232 | + enum virtchnl_proto_hdr_type type; |
| 233 | + u32 field_selector; /* a bit mask to select field for header type */ |
| 234 | + u8 buffer[64]; |
| 235 | + /** |
| 236 | + * binary buffer in network order for specific header type. |
| 237 | + * For example, if type = VIRTCHNL_PROTO_HDR_IPV4, a IPv4 |
| 238 | + * header is expected to be copied into the buffer. |
| 239 | + */ |
| 240 | +}; |
| 241 | + |
| 242 | +VIRTCHNL_CHECK_STRUCT_LEN(72, virtchnl_proto_hdr); |
| 243 | + |
| 244 | +struct virtchnl_proto_hdrs { |
| 245 | + u8 tunnel_level; |
| 246 | + /** |
| 247 | + * specify where protocol header start from. |
| 248 | + * 0 - from the outer layer |
| 249 | + * 1 - from the first inner layer |
| 250 | + * 2 - from the second inner layer |
| 251 | + * .... |
| 252 | + **/ |
| 253 | + int count; /* the proto layers must < VIRTCHNL_MAX_NUM_PROTO_HDRS */ |
| 254 | + struct virtchnl_proto_hdr proto_hdr[VIRTCHNL_MAX_NUM_PROTO_HDRS]; |
| 255 | +}; |
| 256 | + |
| 257 | +VIRTCHNL_CHECK_STRUCT_LEN(2312, virtchnl_proto_hdrs); |
| 258 | + |
| 259 | /** |
| 260 | * virtchnl_vc_validate_vf_msg |
| 261 | * @ver: Virtchnl version info |
| 262 | -- |
| 263 | 2.17.1 |
| 264 | |