Mohsin Kazmi | 0036dcf | 2022-10-21 17:49:12 +0000 | [diff] [blame] | 1 | .. _gso_doc: |
| 2 | |
| 3 | Generic Segmentation Offload |
| 4 | ============================ |
| 5 | |
| 6 | Overview |
| 7 | ________ |
| 8 | |
| 9 | Modern physical NICs provide offload capabilities to software based network |
| 10 | stacks to transfer some type of the packet processing from CPU to physical |
| 11 | NICs. TCP Segmentation Offload (TSO) is one among many which is provided by |
| 12 | modern physical NICs. Software based network stack can offload big (up to 64KB) |
| 13 | TCP packets to NIC and NIC will segment them into Maximum Segment Size packets. |
| 14 | Hence network stack save CPU cycles by processing few big packets instead of |
| 15 | processing many small packets. |
| 16 | |
| 17 | GSO is software based analogous to TSO which is used by virtual interfaces |
| 18 | i.e. tap, virtio, af_packet, vhost-user etc. Typically, virtual interfaces |
| 19 | provide capability to offload big packets (64KB size). But in reality, they |
| 20 | just pass the packet as it is to the other end without segmenting it. Hence, it |
| 21 | is necessary to validate the support of GSO offloading in whole setup otherwise |
| 22 | packet will be dropped when it will be processed by virtual entity which does |
| 23 | not support GSO. |
| 24 | |
| 25 | The GSO Infrastructure |
| 26 | _______________________ |
| 27 | |
| 28 | Software based network stacks implements GSO packet segmentation in software |
| 29 | where egress interface (virtual or physical) does not support GSO or TSO |
| 30 | offload. VPP implements GSO stack to provide support for software based packet |
| 31 | chunking of GSO packets when egress interface does not support GSO or TSO |
| 32 | offload. |
| 33 | |
| 34 | It is implemented as a feature node on interface-output feature arc. It |
| 35 | implements support for basic GSO, GSO with VXLAN tunnel and GSO with IPIP |
| 36 | tunnel. GSO with Geneve and GSO with NVGRE are not supported today. But one can |
| 37 | enable GSO feature node on tunnel interfaces i.e. IPSEC etc to segment GSO |
| 38 | packets before they will be tunneled. |
| 39 | |
| 40 | Virtual interfaces does not support GSO with tunnels. So, special care is |
| 41 | needed when user configures tunnel(s) along with GSO in the setup. In such case, |
| 42 | either enable GSO feature node on tunnel interface (mean chunk the GSO packets |
| 43 | before they will be encapsulated in tunnel) or disable the GSO offload on the |
| 44 | egress interface (only work for VXLAN tunnel and IPIP tunnel), if it is enabled, |
| 45 | should work fine. |
| 46 | |
| 47 | Similarly, many physical interfaces does not support GSO with tunnels too. User |
| 48 | can do the same configuration as it is mentioned previously for virtual |
| 49 | interfaces. |
| 50 | |
| 51 | Data structures |
| 52 | ^^^^^^^^^^^^^^^ |
| 53 | |
| 54 | VPP ``vlib_buffer_t`` uses ``VNET_BUFFER_F_GSO`` flags to mark the buffer carrying GSO |
| 55 | packet and also contain metadata fields with respect to GSO: |
| 56 | |
| 57 | .. code:: c |
| 58 | |
| 59 | i16 l2_hdr_offset; |
| 60 | i16 l3_hdr_offset; |
| 61 | i16 l4_hdr_offset; |
| 62 | |
| 63 | u16 gso_size; |
| 64 | u16 gso_l4_hdr_sz; |
| 65 | i16 outer_l3_hdr_offset; |
| 66 | i16 outer_l4_hdr_offset; |
| 67 | |
| 68 | Packet header offsets are computed from the reference of ``vlib_buffer_t`` data |
| 69 | pointer. |
| 70 | |
| 71 | ``l2_hdr_offset``, ``l3_hdr_offset`` and ``l4_hdr_offset`` are set on input of checksum |
| 72 | offload or GSO enabled interfaces or features i.e. host stack. Appropriate |
| 73 | offload flags are also set to ``vnet_buffer_oflags_t`` to reflect the actual packet |
| 74 | offloads which will be used later at egress interface tx node or |
| 75 | interface-output node or GSO node to process the packet appropriately. These |
| 76 | fields are present in 1st cache line and does not incur extra cycles as most of |
| 77 | the VPP features fetch the ``vlib_buffer_t`` 1st cache line to access ``current_data`` |
| 78 | or ``current_length`` fields of the packet. |
| 79 | |
| 80 | Please note that ``gso_size``, ``gso_l4_hdr_sz``, ``outer_l3_hdr_offset`` and |
| 81 | ``outer_l4_hdr_offset`` are in second cache line of ``vlib_buffer_t``. Accessing them in |
| 82 | data plane will incur some extra cycles but cost of these cycles will be |
| 83 | amortized over (up to 64KB) packet. |
| 84 | |
| 85 | The ``gso_size`` and ``gso_l4_hdr_sz`` are set on input of GSO enabled interfaces (tap, |
| 86 | virtio, af_packet etc) or features (vpp host stack), when we receive a GSO |
| 87 | packet (a chain of buffers with the first one having ``VNET_BUFFER_F_GSO`` bit set), |
| 88 | and needs to persist all the way to the interface-output, in case the egress |
| 89 | interface is not GSO-enabled - then we need to perform the segmentation, and use |
| 90 | these values to chunk the payload appropriately. |
| 91 | |
| 92 | ``outer_l3_hdr_offset`` and ``outer_l4_hdr_offset`` are used in case of tunneled packet |
| 93 | (i.e. VXLAN or IPIP). ``outer_l3_hdr_offset`` will point to outer l3 header of the |
| 94 | tunnel headers and ``outer_l4_hdr_offset`` will point to outer l4 header of the |
| 95 | tunnel headers, if any. |
| 96 | |
| 97 | Following are the helper functions used to set and clear the offload flags from |
| 98 | ``vlib_buffer_t`` metadata: |
| 99 | |
| 100 | .. code:: c |
| 101 | |
| 102 | static_always_inline void |
| 103 | vnet_buffer_offload_flags_set (vlib_buffer_t *b, vnet_buffer_oflags_t oflags) |
| 104 | { |
| 105 | if (b->flags & VNET_BUFFER_F_OFFLOAD) |
| 106 | { |
| 107 | /* add a flag to existing offload */ |
| 108 | vnet_buffer (b)->oflags |= oflags; |
| 109 | } |
| 110 | else |
| 111 | { |
| 112 | /* no offload yet: reset offload flags to new value */ |
| 113 | vnet_buffer (b)->oflags = oflags; |
| 114 | b->flags |= VNET_BUFFER_F_OFFLOAD; |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | static_always_inline void |
| 119 | vnet_buffer_offload_flags_clear (vlib_buffer_t *b, vnet_buffer_oflags_t oflags) |
| 120 | { |
| 121 | vnet_buffer (b)->oflags &= ~oflags; |
| 122 | if (0 == vnet_buffer (b)->oflags) |
| 123 | b->flags &= ~VNET_BUFFER_F_OFFLOAD; |
| 124 | } |
| 125 | |
| 126 | |
| 127 | ENABLE GSO FEATURE NODE |
| 128 | ----------------------- |
| 129 | |
| 130 | GSO feature node is not enabled by default when egress interface does not |
| 131 | support GSO. User has to enable it explicitly using api or cli. |
| 132 | |
| 133 | GSO API |
| 134 | ^^^^^^^ |
| 135 | |
| 136 | This API message is used to enable GSO feature node on an interface. |
| 137 | |
| 138 | .. code:: c |
| 139 | |
| 140 | autoreply define feature_gso_enable_disable |
| 141 | { |
| 142 | u32 client_index; |
| 143 | u32 context; |
| 144 | vl_api_interface_index_t sw_if_index; |
| 145 | bool enable_disable; |
| 146 | option vat_help = "<intfc> | sw_if_index <nn> [enable | disable]"; |
| 147 | }; |
| 148 | |
| 149 | GSO CLI |
| 150 | ^^^^^^^ |
| 151 | |
| 152 | :: |
| 153 | |
| 154 | set interface feature gso <intfc> [enable | disable] |