Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xsk: Add TX timestamp and TX checksum offload support

This change actually defines the (initial) metadata layout
that should be used by AF_XDP userspace (xsk_tx_metadata).
The first field is flags which requests appropriate offloads,
followed by the offload-specific fields. The supported per-device
offloads are exported via netlink (new xsk-flags).

The offloads themselves are still implemented in a bit of a
framework-y fashion that's left from my initial kfunc attempt.
I'm introducing new xsk_tx_metadata_ops which drivers are
supposed to implement. The drivers are also supposed
to call xsk_tx_metadata_request/xsk_tx_metadata_complete in
the right places. Since xsk_tx_metadata_{request,_complete}
are static inline, we don't incur any extra overhead doing
indirect calls.

The benefit of this scheme is as follows:
- keeps all metadata layout parsing away from driver code
- makes it easy to grep and see which drivers implement what
- don't need any extra flags to maintain to keep track of what
offloads are implemented; if the callback is implemented - the offload
is supported (used by netlink reporting code)

Two offloads are defined right now:
1. XDP_TXMD_FLAGS_CHECKSUM: skb-style csum_start+csum_offset
2. XDP_TXMD_FLAGS_TIMESTAMP: writes TX timestamp back into metadata
area upon completion (tx_timestamp field)

XDP_TXMD_FLAGS_TIMESTAMP is also implemented for XDP_COPY mode: it writes
SW timestamp from the skb destructor (note I'm reusing hwtstamps to pass
metadata pointer).

The struct is forward-compatible and can be extended in the future
by appending more fields.

Reviewed-by: Song Yoong Siang <yoong.siang.song@intel.com>
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Link: https://lore.kernel.org/r/20231127190319.1190813-3-sdf@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Stanislav Fomichev and committed by
Alexei Starovoitov
48eb03dd 341ac980

+348 -9
+18 -1
Documentation/netlink/specs/netdev.yaml
··· 45 45 - 46 46 type: flags 47 47 name: xdp-rx-metadata 48 - render-max: true 49 48 entries: 50 49 - 51 50 name: timestamp ··· 54 55 name: hash 55 56 doc: 56 57 Device is capable of exposing receive packet hash via bpf_xdp_metadata_rx_hash(). 58 + - 59 + type: flags 60 + name: xsk-flags 61 + entries: 62 + - 63 + name: tx-timestamp 64 + doc: 65 + HW timestamping egress packets is supported by the driver. 66 + - 67 + name: tx-checksum 68 + doc: 69 + L3 checksum HW offload is supported by the driver. 57 70 58 71 attribute-sets: 59 72 - ··· 97 86 See Documentation/networking/xdp-rx-metadata.rst for more details. 98 87 type: u64 99 88 enum: xdp-rx-metadata 89 + - 90 + name: xsk-features 91 + doc: Bitmask of enabled AF_XDP features. 92 + type: u64 93 + enum: xsk-flags 100 94 101 95 operations: 102 96 list: ··· 119 103 - xdp-features 120 104 - xdp-zc-max-segs 121 105 - xdp-rx-metadata-features 106 + - xsk-features 122 107 dump: 123 108 reply: *dev-all 124 109 -
+2
include/linux/netdevice.h
··· 1865 1865 * @netdev_ops: Includes several pointers to callbacks, 1866 1866 * if one wants to override the ndo_*() functions 1867 1867 * @xdp_metadata_ops: Includes pointers to XDP metadata callbacks. 1868 + * @xsk_tx_metadata_ops: Includes pointers to AF_XDP TX metadata callbacks. 1868 1869 * @ethtool_ops: Management operations 1869 1870 * @l3mdev_ops: Layer 3 master device operations 1870 1871 * @ndisc_ops: Includes callbacks for different IPv6 neighbour ··· 2129 2128 unsigned long long priv_flags; 2130 2129 const struct net_device_ops *netdev_ops; 2131 2130 const struct xdp_metadata_ops *xdp_metadata_ops; 2131 + const struct xsk_tx_metadata_ops *xsk_tx_metadata_ops; 2132 2132 int ifindex; 2133 2133 unsigned short gflags; 2134 2134 unsigned short hard_header_len;
+13 -1
include/linux/skbuff.h
··· 566 566 int mm_account_pinned_pages(struct mmpin *mmp, size_t size); 567 567 void mm_unaccount_pinned_pages(struct mmpin *mmp); 568 568 569 + /* Preserve some data across TX submission and completion. 570 + * 571 + * Note, this state is stored in the driver. Extending the layout 572 + * might need some special care. 573 + */ 574 + struct xsk_tx_metadata_compl { 575 + __u64 *tx_timestamp; 576 + }; 577 + 569 578 /* This data is invariant across clones and lives at 570 579 * the end of the header data, ie. at skb->end. 571 580 */ ··· 587 578 /* Warning: this field is not always filled in (UFO)! */ 588 579 unsigned short gso_segs; 589 580 struct sk_buff *frag_list; 590 - struct skb_shared_hwtstamps hwtstamps; 581 + union { 582 + struct skb_shared_hwtstamps hwtstamps; 583 + struct xsk_tx_metadata_compl xsk_meta; 584 + }; 591 585 unsigned int gso_type; 592 586 u32 tskey; 593 587
+110
include/net/xdp_sock.h
··· 93 93 struct xsk_queue *cq_tmp; /* Only as tmp storage before bind */ 94 94 }; 95 95 96 + /* 97 + * AF_XDP TX metadata hooks for network devices. 98 + * The following hooks can be defined; unless noted otherwise, they are 99 + * optional and can be filled with a null pointer. 100 + * 101 + * void (*tmo_request_timestamp)(void *priv) 102 + * Called when AF_XDP frame requested egress timestamp. 103 + * 104 + * u64 (*tmo_fill_timestamp)(void *priv) 105 + * Called when AF_XDP frame, that had requested egress timestamp, 106 + * received a completion. The hook needs to return the actual HW timestamp. 107 + * 108 + * void (*tmo_request_checksum)(u16 csum_start, u16 csum_offset, void *priv) 109 + * Called when AF_XDP frame requested HW checksum offload. csum_start 110 + * indicates position where checksumming should start. 111 + * csum_offset indicates position where checksum should be stored. 112 + * 113 + */ 114 + struct xsk_tx_metadata_ops { 115 + void (*tmo_request_timestamp)(void *priv); 116 + u64 (*tmo_fill_timestamp)(void *priv); 117 + void (*tmo_request_checksum)(u16 csum_start, u16 csum_offset, void *priv); 118 + }; 119 + 96 120 #ifdef CONFIG_XDP_SOCKETS 97 121 98 122 int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp); 99 123 int __xsk_map_redirect(struct xdp_sock *xs, struct xdp_buff *xdp); 100 124 void __xsk_map_flush(void); 125 + 126 + /** 127 + * xsk_tx_metadata_to_compl - Save enough relevant metadata information 128 + * to perform tx completion in the future. 129 + * @meta: pointer to AF_XDP metadata area 130 + * @compl: pointer to output struct xsk_tx_metadata_to_compl 131 + * 132 + * This function should be called by the networking device when 133 + * it prepares AF_XDP egress packet. The value of @compl should be stored 134 + * and passed to xsk_tx_metadata_complete upon TX completion. 135 + */ 136 + static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta, 137 + struct xsk_tx_metadata_compl *compl) 138 + { 139 + if (!meta) 140 + return; 141 + 142 + if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP) 143 + compl->tx_timestamp = &meta->completion.tx_timestamp; 144 + else 145 + compl->tx_timestamp = NULL; 146 + } 147 + 148 + /** 149 + * xsk_tx_metadata_request - Evaluate AF_XDP TX metadata at submission 150 + * and call appropriate xsk_tx_metadata_ops operation. 151 + * @meta: pointer to AF_XDP metadata area 152 + * @ops: pointer to struct xsk_tx_metadata_ops 153 + * @priv: pointer to driver-private aread 154 + * 155 + * This function should be called by the networking device when 156 + * it prepares AF_XDP egress packet. 157 + */ 158 + static inline void xsk_tx_metadata_request(const struct xsk_tx_metadata *meta, 159 + const struct xsk_tx_metadata_ops *ops, 160 + void *priv) 161 + { 162 + if (!meta) 163 + return; 164 + 165 + if (ops->tmo_request_timestamp) 166 + if (meta->flags & XDP_TXMD_FLAGS_TIMESTAMP) 167 + ops->tmo_request_timestamp(priv); 168 + 169 + if (ops->tmo_request_checksum) 170 + if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM) 171 + ops->tmo_request_checksum(meta->request.csum_start, 172 + meta->request.csum_offset, priv); 173 + } 174 + 175 + /** 176 + * xsk_tx_metadata_complete - Evaluate AF_XDP TX metadata at completion 177 + * and call appropriate xsk_tx_metadata_ops operation. 178 + * @compl: pointer to completion metadata produced from xsk_tx_metadata_to_compl 179 + * @ops: pointer to struct xsk_tx_metadata_ops 180 + * @priv: pointer to driver-private aread 181 + * 182 + * This function should be called by the networking device upon 183 + * AF_XDP egress completion. 184 + */ 185 + static inline void xsk_tx_metadata_complete(struct xsk_tx_metadata_compl *compl, 186 + const struct xsk_tx_metadata_ops *ops, 187 + void *priv) 188 + { 189 + if (!compl) 190 + return; 191 + 192 + *compl->tx_timestamp = ops->tmo_fill_timestamp(priv); 193 + } 101 194 102 195 #else 103 196 ··· 205 112 } 206 113 207 114 static inline void __xsk_map_flush(void) 115 + { 116 + } 117 + 118 + static inline void xsk_tx_metadata_to_compl(struct xsk_tx_metadata *meta, 119 + struct xsk_tx_metadata_compl *compl) 120 + { 121 + } 122 + 123 + static inline void xsk_tx_metadata_request(struct xsk_tx_metadata *meta, 124 + const struct xsk_tx_metadata_ops *ops, 125 + void *priv) 126 + { 127 + } 128 + 129 + static inline void xsk_tx_metadata_complete(struct xsk_tx_metadata_compl *compl, 130 + const struct xsk_tx_metadata_ops *ops, 131 + void *priv) 208 132 { 209 133 } 210 134
+13
include/net/xdp_sock_drv.h
··· 165 165 return xp_raw_get_data(pool, addr); 166 166 } 167 167 168 + static inline struct xsk_tx_metadata *xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr) 169 + { 170 + if (!pool->tx_metadata_len) 171 + return NULL; 172 + 173 + return xp_raw_get_data(pool, addr) - pool->tx_metadata_len; 174 + } 175 + 168 176 static inline void xsk_buff_dma_sync_for_cpu(struct xdp_buff *xdp, struct xsk_buff_pool *pool) 169 177 { 170 178 struct xdp_buff_xsk *xskb = container_of(xdp, struct xdp_buff_xsk, xdp); ··· 328 320 } 329 321 330 322 static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr) 323 + { 324 + return NULL; 325 + } 326 + 327 + static inline struct xsk_tx_metadata *xsk_buff_get_metadata(struct xsk_buff_pool *pool, u64 addr) 331 328 { 332 329 return NULL; 333 330 }
+6
include/net/xsk_buff_pool.h
··· 33 33 }; 34 34 35 35 #define XSK_CHECK_PRIV_TYPE(t) BUILD_BUG_ON(sizeof(t) > offsetofend(struct xdp_buff_xsk, cb)) 36 + #define XSK_TX_COMPL_FITS(t) BUILD_BUG_ON(sizeof(struct xsk_tx_metadata_compl) > sizeof(t)) 36 37 37 38 struct xsk_dma_map { 38 39 dma_addr_t *dma_pages; ··· 233 232 if (!xskb->pool->unaligned) 234 233 return xskb->orig_addr + offset; 235 234 return xskb->orig_addr + (offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT); 235 + } 236 + 237 + static inline bool xp_tx_metadata_enabled(const struct xsk_buff_pool *pool) 238 + { 239 + return pool->tx_metadata_len > 0; 236 240 } 237 241 238 242 #endif /* XSK_BUFF_POOL_H_ */
+38
include/uapi/linux/if_xdp.h
··· 106 106 #define XSK_UNALIGNED_BUF_ADDR_MASK \ 107 107 ((1ULL << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1) 108 108 109 + /* Request transmit timestamp. Upon completion, put it into tx_timestamp 110 + * field of struct xsk_tx_metadata. 111 + */ 112 + #define XDP_TXMD_FLAGS_TIMESTAMP (1 << 0) 113 + 114 + /* Request transmit checksum offload. Checksum start position and offset 115 + * are communicated via csum_start and csum_offset fields of struct 116 + * xsk_tx_metadata. 117 + */ 118 + #define XDP_TXMD_FLAGS_CHECKSUM (1 << 1) 119 + 120 + /* AF_XDP offloads request. 'request' union member is consumed by the driver 121 + * when the packet is being transmitted. 'completion' union member is 122 + * filled by the driver when the transmit completion arrives. 123 + */ 124 + struct xsk_tx_metadata { 125 + __u64 flags; 126 + 127 + union { 128 + struct { 129 + /* XDP_TXMD_FLAGS_CHECKSUM */ 130 + 131 + /* Offset from desc->addr where checksumming should start. */ 132 + __u16 csum_start; 133 + /* Offset from csum_start where checksum should be stored. */ 134 + __u16 csum_offset; 135 + } request; 136 + 137 + struct { 138 + /* XDP_TXMD_FLAGS_TIMESTAMP */ 139 + __u64 tx_timestamp; 140 + } completion; 141 + }; 142 + }; 143 + 109 144 /* Rx/Tx descriptor */ 110 145 struct xdp_desc { 111 146 __u64 addr; ··· 156 121 * to 0 and this maintains backward compatibility. 157 122 */ 158 123 #define XDP_PKT_CONTD (1 << 0) 124 + 125 + /* TX packet carries valid metadata. */ 126 + #define XDP_TX_METADATA (1 << 1) 159 127 160 128 #endif /* _LINUX_IF_XDP_H */
+16
include/uapi/linux/netdev.h
··· 53 53 NETDEV_XDP_RX_METADATA_MASK = 3, 54 54 }; 55 55 56 + /** 57 + * enum netdev_xsk_flags 58 + * @NETDEV_XSK_FLAGS_TX_TIMESTAMP: HW timestamping egress packets is supported 59 + * by the driver. 60 + * @NETDEV_XSK_FLAGS_TX_CHECKSUM: L3 checksum HW offload is supported by the 61 + * driver. 62 + */ 63 + enum netdev_xsk_flags { 64 + NETDEV_XSK_FLAGS_TX_TIMESTAMP = 1, 65 + NETDEV_XSK_FLAGS_TX_CHECKSUM = 2, 66 + 67 + /* private: */ 68 + NETDEV_XSK_FLAGS_MASK = 3, 69 + }; 70 + 56 71 enum { 57 72 NETDEV_A_DEV_IFINDEX = 1, 58 73 NETDEV_A_DEV_PAD, 59 74 NETDEV_A_DEV_XDP_FEATURES, 60 75 NETDEV_A_DEV_XDP_ZC_MAX_SEGS, 61 76 NETDEV_A_DEV_XDP_RX_METADATA_FEATURES, 77 + NETDEV_A_DEV_XSK_FEATURES, 62 78 63 79 __NETDEV_A_DEV_MAX, 64 80 NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
+12 -1
net/core/netdev-genl.c
··· 6 6 #include <net/net_namespace.h> 7 7 #include <net/sock.h> 8 8 #include <net/xdp.h> 9 + #include <net/xdp_sock.h> 9 10 10 11 #include "netdev-genl-gen.h" 11 12 ··· 14 13 netdev_nl_dev_fill(struct net_device *netdev, struct sk_buff *rsp, 15 14 const struct genl_info *info) 16 15 { 16 + u64 xsk_features = 0; 17 17 u64 xdp_rx_meta = 0; 18 18 void *hdr; 19 19 ··· 28 26 XDP_METADATA_KFUNC_xxx 29 27 #undef XDP_METADATA_KFUNC 30 28 29 + if (netdev->xsk_tx_metadata_ops) { 30 + if (netdev->xsk_tx_metadata_ops->tmo_fill_timestamp) 31 + xsk_features |= NETDEV_XSK_FLAGS_TX_TIMESTAMP; 32 + if (netdev->xsk_tx_metadata_ops->tmo_request_checksum) 33 + xsk_features |= NETDEV_XSK_FLAGS_TX_CHECKSUM; 34 + } 35 + 31 36 if (nla_put_u32(rsp, NETDEV_A_DEV_IFINDEX, netdev->ifindex) || 32 37 nla_put_u64_64bit(rsp, NETDEV_A_DEV_XDP_FEATURES, 33 38 netdev->xdp_features, NETDEV_A_DEV_PAD) || 34 39 nla_put_u64_64bit(rsp, NETDEV_A_DEV_XDP_RX_METADATA_FEATURES, 35 - xdp_rx_meta, NETDEV_A_DEV_PAD)) { 40 + xdp_rx_meta, NETDEV_A_DEV_PAD) || 41 + nla_put_u64_64bit(rsp, NETDEV_A_DEV_XSK_FEATURES, 42 + xsk_features, NETDEV_A_DEV_PAD)) { 36 43 genlmsg_cancel(rsp, hdr); 37 44 return -EINVAL; 38 45 }
+34
net/xdp/xsk.c
··· 571 571 572 572 static void xsk_destruct_skb(struct sk_buff *skb) 573 573 { 574 + struct xsk_tx_metadata_compl *compl = &skb_shinfo(skb)->xsk_meta; 575 + 576 + if (compl->tx_timestamp) { 577 + /* sw completion timestamp, not a real one */ 578 + *compl->tx_timestamp = ktime_get_tai_fast_ns(); 579 + } 580 + 574 581 xsk_cq_submit_locked(xdp_sk(skb->sk), xsk_get_num_desc(skb)); 575 582 sock_wfree(skb); 576 583 } ··· 662 655 static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, 663 656 struct xdp_desc *desc) 664 657 { 658 + struct xsk_tx_metadata *meta = NULL; 665 659 struct net_device *dev = xs->dev; 666 660 struct sk_buff *skb = xs->skb; 661 + bool first_frag = false; 667 662 int err; 668 663 669 664 if (dev->priv_flags & IFF_TX_SKB_NO_LINEAR) { ··· 696 687 kfree_skb(skb); 697 688 goto free_err; 698 689 } 690 + 691 + first_frag = true; 699 692 } else { 700 693 int nr_frags = skb_shinfo(skb)->nr_frags; 701 694 struct page *page; ··· 720 709 721 710 skb_add_rx_frag(skb, nr_frags, page, 0, len, 0); 722 711 } 712 + 713 + if (first_frag && desc->options & XDP_TX_METADATA) { 714 + if (unlikely(xs->pool->tx_metadata_len == 0)) { 715 + err = -EINVAL; 716 + goto free_err; 717 + } 718 + 719 + meta = buffer - xs->pool->tx_metadata_len; 720 + 721 + if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM) { 722 + if (unlikely(meta->request.csum_start + 723 + meta->request.csum_offset + 724 + sizeof(__sum16) > len)) { 725 + err = -EINVAL; 726 + goto free_err; 727 + } 728 + 729 + skb->csum_start = hr + meta->request.csum_start; 730 + skb->csum_offset = meta->request.csum_offset; 731 + skb->ip_summed = CHECKSUM_PARTIAL; 732 + } 733 + } 723 734 } 724 735 725 736 skb->dev = dev; 726 737 skb->priority = READ_ONCE(xs->sk.sk_priority); 727 738 skb->mark = READ_ONCE(xs->sk.sk_mark); 728 739 skb->destructor = xsk_destruct_skb; 740 + xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta); 729 741 xsk_set_destructor_arg(skb); 730 742 731 743 return skb;
+1 -1
net/xdp/xsk_queue.h
··· 137 137 138 138 static inline bool xp_unused_options_set(u32 options) 139 139 { 140 - return options & ~XDP_PKT_CONTD; 140 + return options & ~(XDP_PKT_CONTD | XDP_TX_METADATA); 141 141 } 142 142 143 143 static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool,
+47 -5
tools/include/uapi/linux/if_xdp.h
··· 26 26 */ 27 27 #define XDP_USE_NEED_WAKEUP (1 << 3) 28 28 /* By setting this option, userspace application indicates that it can 29 - * handle multiple descriptors per packet thus enabling xsk core to split 29 + * handle multiple descriptors per packet thus enabling AF_XDP to split 30 30 * multi-buffer XDP frames into multiple Rx descriptors. Without this set 31 - * such frames will be dropped by xsk. 31 + * such frames will be dropped. 32 32 */ 33 - #define XDP_USE_SG (1 << 4) 33 + #define XDP_USE_SG (1 << 4) 34 34 35 35 /* Flags for xsk_umem_config flags */ 36 36 #define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0) ··· 106 106 #define XSK_UNALIGNED_BUF_ADDR_MASK \ 107 107 ((1ULL << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1) 108 108 109 + /* Request transmit timestamp. Upon completion, put it into tx_timestamp 110 + * field of union xsk_tx_metadata. 111 + */ 112 + #define XDP_TXMD_FLAGS_TIMESTAMP (1 << 0) 113 + 114 + /* Request transmit checksum offload. Checksum start position and offset 115 + * are communicated via csum_start and csum_offset fields of union 116 + * xsk_tx_metadata. 117 + */ 118 + #define XDP_TXMD_FLAGS_CHECKSUM (1 << 1) 119 + 120 + /* AF_XDP offloads request. 'request' union member is consumed by the driver 121 + * when the packet is being transmitted. 'completion' union member is 122 + * filled by the driver when the transmit completion arrives. 123 + */ 124 + struct xsk_tx_metadata { 125 + __u64 flags; 126 + 127 + union { 128 + struct { 129 + /* XDP_TXMD_FLAGS_CHECKSUM */ 130 + 131 + /* Offset from desc->addr where checksumming should start. */ 132 + __u16 csum_start; 133 + /* Offset from csum_start where checksum should be stored. */ 134 + __u16 csum_offset; 135 + } request; 136 + 137 + struct { 138 + /* XDP_TXMD_FLAGS_TIMESTAMP */ 139 + __u64 tx_timestamp; 140 + } completion; 141 + }; 142 + }; 143 + 109 144 /* Rx/Tx descriptor */ 110 145 struct xdp_desc { 111 146 __u64 addr; ··· 148 113 __u32 options; 149 114 }; 150 115 151 - /* Flag indicating packet constitutes of multiple buffers*/ 116 + /* UMEM descriptor is __u64 */ 117 + 118 + /* Flag indicating that the packet continues with the buffer pointed out by the 119 + * next frame in the ring. The end of the packet is signalled by setting this 120 + * bit to zero. For single buffer packets, every descriptor has 'options' set 121 + * to 0 and this maintains backward compatibility. 122 + */ 152 123 #define XDP_PKT_CONTD (1 << 0) 153 124 154 - /* UMEM descriptor is __u64 */ 125 + /* TX packet carries valid metadata. */ 126 + #define XDP_TX_METADATA (1 << 1) 155 127 156 128 #endif /* _LINUX_IF_XDP_H */
+16
tools/include/uapi/linux/netdev.h
··· 53 53 NETDEV_XDP_RX_METADATA_MASK = 3, 54 54 }; 55 55 56 + /** 57 + * enum netdev_xsk_flags 58 + * @NETDEV_XSK_FLAGS_TX_TIMESTAMP: HW timestamping egress packets is supported 59 + * by the driver. 60 + * @NETDEV_XSK_FLAGS_TX_CHECKSUM: L3 checksum HW offload is supported by the 61 + * driver. 62 + */ 63 + enum netdev_xsk_flags { 64 + NETDEV_XSK_FLAGS_TX_TIMESTAMP = 1, 65 + NETDEV_XSK_FLAGS_TX_CHECKSUM = 2, 66 + 67 + /* private: */ 68 + NETDEV_XSK_FLAGS_MASK = 3, 69 + }; 70 + 56 71 enum { 57 72 NETDEV_A_DEV_IFINDEX = 1, 58 73 NETDEV_A_DEV_PAD, 59 74 NETDEV_A_DEV_XDP_FEATURES, 60 75 NETDEV_A_DEV_XDP_ZC_MAX_SEGS, 61 76 NETDEV_A_DEV_XDP_RX_METADATA_FEATURES, 77 + NETDEV_A_DEV_XSK_FEATURES, 62 78 63 79 __NETDEV_A_DEV_MAX, 64 80 NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
+19
tools/net/ynl/generated/netdev-user.c
··· 58 58 return netdev_xdp_rx_metadata_strmap[value]; 59 59 } 60 60 61 + static const char * const netdev_xsk_flags_strmap[] = { 62 + [0] = "tx-timestamp", 63 + [1] = "tx-checksum", 64 + }; 65 + 66 + const char *netdev_xsk_flags_str(enum netdev_xsk_flags value) 67 + { 68 + value = ffs(value) - 1; 69 + if (value < 0 || value >= (int)MNL_ARRAY_SIZE(netdev_xsk_flags_strmap)) 70 + return NULL; 71 + return netdev_xsk_flags_strmap[value]; 72 + } 73 + 61 74 /* Policies */ 62 75 struct ynl_policy_attr netdev_dev_policy[NETDEV_A_DEV_MAX + 1] = { 63 76 [NETDEV_A_DEV_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, }, ··· 78 65 [NETDEV_A_DEV_XDP_FEATURES] = { .name = "xdp-features", .type = YNL_PT_U64, }, 79 66 [NETDEV_A_DEV_XDP_ZC_MAX_SEGS] = { .name = "xdp-zc-max-segs", .type = YNL_PT_U32, }, 80 67 [NETDEV_A_DEV_XDP_RX_METADATA_FEATURES] = { .name = "xdp-rx-metadata-features", .type = YNL_PT_U64, }, 68 + [NETDEV_A_DEV_XSK_FEATURES] = { .name = "xsk-features", .type = YNL_PT_U64, }, 81 69 }; 82 70 83 71 struct ynl_policy_nest netdev_dev_nest = { ··· 130 116 return MNL_CB_ERROR; 131 117 dst->_present.xdp_rx_metadata_features = 1; 132 118 dst->xdp_rx_metadata_features = mnl_attr_get_u64(attr); 119 + } else if (type == NETDEV_A_DEV_XSK_FEATURES) { 120 + if (ynl_attr_validate(yarg, attr)) 121 + return MNL_CB_ERROR; 122 + dst->_present.xsk_features = 1; 123 + dst->xsk_features = mnl_attr_get_u64(attr); 133 124 } 134 125 } 135 126
+3
tools/net/ynl/generated/netdev-user.h
··· 19 19 const char *netdev_op_str(int op); 20 20 const char *netdev_xdp_act_str(enum netdev_xdp_act value); 21 21 const char *netdev_xdp_rx_metadata_str(enum netdev_xdp_rx_metadata value); 22 + const char *netdev_xsk_flags_str(enum netdev_xsk_flags value); 22 23 23 24 /* Common nested types */ 24 25 /* ============== NETDEV_CMD_DEV_GET ============== */ ··· 51 50 __u32 xdp_features:1; 52 51 __u32 xdp_zc_max_segs:1; 53 52 __u32 xdp_rx_metadata_features:1; 53 + __u32 xsk_features:1; 54 54 } _present; 55 55 56 56 __u32 ifindex; 57 57 __u64 xdp_features; 58 58 __u32 xdp_zc_max_segs; 59 59 __u64 xdp_rx_metadata_features; 60 + __u64 xsk_features; 60 61 }; 61 62 62 63 void netdev_dev_get_rsp_free(struct netdev_dev_get_rsp *rsp);