Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 1 | /* |
| 2 | * QEMU network structures definitions and helper functions |
| 3 | * |
| 4 | * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com) |
| 5 | * |
| 6 | * Developed by Daynix Computing LTD (http://www.daynix.com) |
| 7 | * |
| 8 | * Portions developed by Free Software Foundation, Inc |
| 9 | * Copyright (C) 1991-1997, 2001, 2003, 2006 Free Software Foundation, Inc. |
| 10 | * See netinet/ip6.h and netinet/in.h (GNU C Library) |
| 11 | * |
| 12 | * Portions developed by Igor Kovalenko |
| 13 | * Copyright (c) 2006 Igor Kovalenko |
| 14 | * See hw/rtl8139.c (QEMU) |
| 15 | * |
| 16 | * Authors: |
| 17 | * Dmitry Fleytman <dmitry@daynix.com> |
| 18 | * Tamir Shomer <tamirs@daynix.com> |
| 19 | * Yan Vugenfirer <yan@daynix.com> |
| 20 | * |
| 21 | * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| 22 | * See the COPYING file in the top-level directory. |
| 23 | * |
| 24 | */ |
| 25 | |
| 26 | #ifndef QEMU_ETH_H |
| 27 | #define QEMU_ETH_H |
| 28 | |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 29 | #include "qemu/bswap.h" |
| 30 | #include "qemu/iov.h" |
| 31 | |
| 32 | #define ETH_ALEN 6 |
Dr. David Alan Gilbert | 9c7ffe2 | 2016-01-08 14:41:28 +0000 | [diff] [blame] | 33 | #define ETH_HLEN 14 |
Bin Meng | af77451 | 2021-03-17 14:26:27 +0800 | [diff] [blame] | 34 | #define ETH_ZLEN 60 /* Min. octets in frame without FCS */ |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 35 | |
| 36 | struct eth_header { |
| 37 | uint8_t h_dest[ETH_ALEN]; /* destination eth addr */ |
| 38 | uint8_t h_source[ETH_ALEN]; /* source ether addr */ |
| 39 | uint16_t h_proto; /* packet type ID field */ |
| 40 | }; |
| 41 | |
| 42 | struct vlan_header { |
| 43 | uint16_t h_tci; /* priority and VLAN ID */ |
| 44 | uint16_t h_proto; /* encapsulated protocol */ |
| 45 | }; |
| 46 | |
| 47 | struct ip_header { |
| 48 | uint8_t ip_ver_len; /* version and header length */ |
| 49 | uint8_t ip_tos; /* type of service */ |
| 50 | uint16_t ip_len; /* total length */ |
| 51 | uint16_t ip_id; /* identification */ |
| 52 | uint16_t ip_off; /* fragment offset field */ |
| 53 | uint8_t ip_ttl; /* time to live */ |
| 54 | uint8_t ip_p; /* protocol */ |
| 55 | uint16_t ip_sum; /* checksum */ |
| 56 | uint32_t ip_src, ip_dst; /* source and destination address */ |
| 57 | }; |
| 58 | |
| 59 | typedef struct tcp_header { |
| 60 | uint16_t th_sport; /* source port */ |
| 61 | uint16_t th_dport; /* destination port */ |
| 62 | uint32_t th_seq; /* sequence number */ |
| 63 | uint32_t th_ack; /* acknowledgment number */ |
| 64 | uint16_t th_offset_flags; /* data offset, reserved 6 bits, */ |
| 65 | /* TCP protocol flags */ |
| 66 | uint16_t th_win; /* window */ |
| 67 | uint16_t th_sum; /* checksum */ |
| 68 | uint16_t th_urp; /* urgent pointer */ |
| 69 | } tcp_header; |
| 70 | |
Dmitry Fleytman | 66409b7 | 2016-06-01 11:23:40 +0300 | [diff] [blame] | 71 | #define TCP_FLAGS_ONLY(flags) ((flags) & 0x3f) |
| 72 | |
| 73 | #define TCP_HEADER_FLAGS(tcp) \ |
| 74 | TCP_FLAGS_ONLY(be16_to_cpu((tcp)->th_offset_flags)) |
| 75 | |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 76 | #define TCP_FLAG_ACK 0x10 |
| 77 | |
Dmitry Fleytman | 66409b7 | 2016-06-01 11:23:40 +0300 | [diff] [blame] | 78 | #define TCP_HEADER_DATA_OFFSET(tcp) \ |
| 79 | (((be16_to_cpu((tcp)->th_offset_flags) >> 12) & 0xf) << 2) |
| 80 | |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 81 | typedef struct udp_header { |
| 82 | uint16_t uh_sport; /* source port */ |
| 83 | uint16_t uh_dport; /* destination port */ |
| 84 | uint16_t uh_ulen; /* udp length */ |
| 85 | uint16_t uh_sum; /* udp checksum */ |
| 86 | } udp_header; |
| 87 | |
| 88 | typedef struct ip_pseudo_header { |
| 89 | uint32_t ip_src; |
| 90 | uint32_t ip_dst; |
| 91 | uint8_t zeros; |
| 92 | uint8_t ip_proto; |
| 93 | uint16_t ip_payload; |
| 94 | } ip_pseudo_header; |
| 95 | |
| 96 | /* IPv6 address */ |
Dmitry Krivenok | d60b20c | 2013-10-21 12:08:44 +0400 | [diff] [blame] | 97 | struct in6_address { |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 98 | union { |
| 99 | uint8_t __u6_addr8[16]; |
| 100 | } __in6_u; |
| 101 | }; |
| 102 | |
| 103 | struct ip6_header { |
| 104 | union { |
| 105 | struct ip6_hdrctl { |
| 106 | uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, |
| 107 | 20 bits flow-ID */ |
| 108 | uint16_t ip6_un1_plen; /* payload length */ |
| 109 | uint8_t ip6_un1_nxt; /* next header */ |
| 110 | uint8_t ip6_un1_hlim; /* hop limit */ |
| 111 | } ip6_un1; |
| 112 | uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ |
| 113 | struct ip6_ecn_access { |
| 114 | uint8_t ip6_un3_vfc; /* 4 bits version, top 4 bits tclass */ |
| 115 | uint8_t ip6_un3_ecn; /* 2 bits ECN, top 6 bits payload length */ |
| 116 | } ip6_un3; |
| 117 | } ip6_ctlun; |
Dmitry Krivenok | d60b20c | 2013-10-21 12:08:44 +0400 | [diff] [blame] | 118 | struct in6_address ip6_src; /* source address */ |
| 119 | struct in6_address ip6_dst; /* destination address */ |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 120 | }; |
| 121 | |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 122 | typedef struct ip6_pseudo_header { |
| 123 | struct in6_address ip6_src; |
| 124 | struct in6_address ip6_dst; |
| 125 | uint32_t len; |
| 126 | uint8_t zero[3]; |
| 127 | uint8_t next_hdr; |
| 128 | } ip6_pseudo_header; |
| 129 | |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 130 | struct ip6_ext_hdr { |
| 131 | uint8_t ip6r_nxt; /* next header */ |
| 132 | uint8_t ip6r_len; /* length in units of 8 octets */ |
| 133 | }; |
| 134 | |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 135 | struct ip6_ext_hdr_routing { |
| 136 | uint8_t nxt; |
| 137 | uint8_t len; |
| 138 | uint8_t rtype; |
| 139 | uint8_t segleft; |
| 140 | uint8_t rsvd[4]; |
| 141 | }; |
| 142 | |
| 143 | struct ip6_option_hdr { |
| 144 | #define IP6_OPT_PAD1 (0x00) |
| 145 | #define IP6_OPT_HOME (0xC9) |
| 146 | uint8_t type; |
| 147 | uint8_t len; |
| 148 | }; |
| 149 | |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 150 | struct udp_hdr { |
| 151 | uint16_t uh_sport; /* source port */ |
| 152 | uint16_t uh_dport; /* destination port */ |
| 153 | uint16_t uh_ulen; /* udp length */ |
| 154 | uint16_t uh_sum; /* udp checksum */ |
| 155 | }; |
| 156 | |
| 157 | struct tcp_hdr { |
| 158 | u_short th_sport; /* source port */ |
| 159 | u_short th_dport; /* destination port */ |
| 160 | uint32_t th_seq; /* sequence number */ |
| 161 | uint32_t th_ack; /* acknowledgment number */ |
| 162 | #ifdef HOST_WORDS_BIGENDIAN |
| 163 | u_char th_off : 4, /* data offset */ |
| 164 | th_x2:4; /* (unused) */ |
| 165 | #else |
| 166 | u_char th_x2 : 4, /* (unused) */ |
| 167 | th_off:4; /* data offset */ |
| 168 | #endif |
| 169 | |
| 170 | #define TH_ELN 0x1 /* explicit loss notification */ |
| 171 | #define TH_ECN 0x2 /* explicit congestion notification */ |
| 172 | #define TH_FS 0x4 /* fast start */ |
| 173 | |
| 174 | u_char th_flags; |
| 175 | #define TH_FIN 0x01 |
| 176 | #define TH_SYN 0x02 |
| 177 | #define TH_RST 0x04 |
| 178 | #define TH_PUSH 0x08 |
| 179 | #define TH_ACK 0x10 |
| 180 | #define TH_URG 0x20 |
Yuri Benditovich | 2974e91 | 2019-01-03 15:12:29 +0200 | [diff] [blame] | 181 | #define TH_ECE 0x40 |
| 182 | #define TH_CWR 0x80 |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 183 | u_short th_win; /* window */ |
| 184 | u_short th_sum; /* checksum */ |
| 185 | u_short th_urp; /* urgent pointer */ |
| 186 | }; |
| 187 | |
| 188 | #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt |
| 189 | #define ip6_ecn_acc ip6_ctlun.ip6_un3.ip6_un3_ecn |
Andrew | e219d30 | 2020-07-16 06:53:24 +0300 | [diff] [blame] | 190 | #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 191 | |
| 192 | #define PKT_GET_ETH_HDR(p) \ |
| 193 | ((struct eth_header *)(p)) |
| 194 | #define PKT_GET_VLAN_HDR(p) \ |
| 195 | ((struct vlan_header *) (((uint8_t *)(p)) + sizeof(struct eth_header))) |
| 196 | #define PKT_GET_DVLAN_HDR(p) \ |
| 197 | (PKT_GET_VLAN_HDR(p) + 1) |
| 198 | #define PKT_GET_IP_HDR(p) \ |
| 199 | ((struct ip_header *)(((uint8_t *)(p)) + eth_get_l2_hdr_length(p))) |
| 200 | #define IP_HDR_GET_LEN(p) \ |
Marc-André Lureau | 4f51e1d | 2018-02-09 20:03:40 +0100 | [diff] [blame] | 201 | ((ldub_p(p + offsetof(struct ip_header, ip_ver_len)) & 0x0F) << 2) |
| 202 | #define IP_HDR_GET_P(p) \ |
| 203 | (ldub_p(p + offsetof(struct ip_header, ip_p))) |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 204 | #define PKT_GET_IP_HDR_LEN(p) \ |
| 205 | (IP_HDR_GET_LEN(PKT_GET_IP_HDR(p))) |
| 206 | #define PKT_GET_IP6_HDR(p) \ |
| 207 | ((struct ip6_header *) (((uint8_t *)(p)) + eth_get_l2_hdr_length(p))) |
| 208 | #define IP_HEADER_VERSION(ip) \ |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 209 | (((ip)->ip_ver_len >> 4) & 0xf) |
| 210 | #define IP4_IS_FRAGMENT(ip) \ |
| 211 | ((be16_to_cpu((ip)->ip_off) & (IP_OFFMASK | IP_MF)) != 0) |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 212 | |
Dr. David Alan Gilbert | 9c7ffe2 | 2016-01-08 14:41:28 +0000 | [diff] [blame] | 213 | #define ETH_P_IP (0x0800) /* Internet Protocol packet */ |
| 214 | #define ETH_P_ARP (0x0806) /* Address Resolution packet */ |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 215 | #define ETH_P_IPV6 (0x86dd) |
| 216 | #define ETH_P_VLAN (0x8100) |
| 217 | #define ETH_P_DVLAN (0x88a8) |
Cédric Le Goater | 47bb83c | 2017-04-14 10:35:03 +0200 | [diff] [blame] | 218 | #define ETH_P_NCSI (0x88f8) |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 219 | #define ETH_P_UNKNOWN (0xffff) |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 220 | #define VLAN_VID_MASK 0x0fff |
| 221 | #define IP_HEADER_VERSION_4 (4) |
| 222 | #define IP_HEADER_VERSION_6 (6) |
| 223 | #define IP_PROTO_TCP (6) |
| 224 | #define IP_PROTO_UDP (17) |
| 225 | #define IPTOS_ECN_MASK 0x03 |
| 226 | #define IPTOS_ECN(x) ((x) & IPTOS_ECN_MASK) |
| 227 | #define IPTOS_ECN_CE 0x03 |
| 228 | #define IP6_ECN_MASK 0xC0 |
| 229 | #define IP6_ECN(x) ((x) & IP6_ECN_MASK) |
| 230 | #define IP6_ECN_CE 0xC0 |
| 231 | #define IP4_DONT_FRAGMENT_FLAG (1 << 14) |
| 232 | |
| 233 | #define IS_SPECIAL_VLAN_ID(x) \ |
| 234 | (((x) == 0) || ((x) == 0xFFF)) |
| 235 | |
| 236 | #define ETH_MAX_L2_HDR_LEN \ |
| 237 | (sizeof(struct eth_header) + 2 * sizeof(struct vlan_header)) |
| 238 | |
| 239 | #define ETH_MAX_IP4_HDR_LEN (60) |
| 240 | #define ETH_MAX_IP_DGRAM_LEN (0xFFFF) |
| 241 | |
| 242 | #define IP_FRAG_UNIT_SIZE (8) |
| 243 | #define IP_FRAG_ALIGN_SIZE(x) ((x) & ~0x7) |
| 244 | #define IP_RF 0x8000 /* reserved fragment flag */ |
| 245 | #define IP_DF 0x4000 /* don't fragment flag */ |
| 246 | #define IP_MF 0x2000 /* more fragments flag */ |
| 247 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ |
| 248 | |
| 249 | #define IP6_EXT_GRANULARITY (8) /* Size granularity for |
| 250 | IPv6 extension headers */ |
| 251 | |
| 252 | /* IP6 extension header types */ |
| 253 | #define IP6_HOP_BY_HOP (0) |
| 254 | #define IP6_ROUTING (43) |
| 255 | #define IP6_FRAGMENT (44) |
| 256 | #define IP6_ESP (50) |
| 257 | #define IP6_AUTHENTICATION (51) |
| 258 | #define IP6_NONE (59) |
| 259 | #define IP6_DESTINATON (60) |
| 260 | #define IP6_MOBILITY (135) |
| 261 | |
| 262 | static inline int is_multicast_ether_addr(const uint8_t *addr) |
| 263 | { |
| 264 | return 0x01 & addr[0]; |
| 265 | } |
| 266 | |
| 267 | static inline int is_broadcast_ether_addr(const uint8_t *addr) |
| 268 | { |
| 269 | return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; |
| 270 | } |
| 271 | |
| 272 | static inline int is_unicast_ether_addr(const uint8_t *addr) |
| 273 | { |
| 274 | return !is_multicast_ether_addr(addr); |
| 275 | } |
| 276 | |
| 277 | typedef enum { |
| 278 | ETH_PKT_UCAST = 0xAABBCC00, |
| 279 | ETH_PKT_BCAST, |
| 280 | ETH_PKT_MCAST |
| 281 | } eth_pkt_types_e; |
| 282 | |
| 283 | static inline eth_pkt_types_e |
| 284 | get_eth_packet_type(const struct eth_header *ehdr) |
| 285 | { |
| 286 | if (is_broadcast_ether_addr(ehdr->h_dest)) { |
| 287 | return ETH_PKT_BCAST; |
| 288 | } else if (is_multicast_ether_addr(ehdr->h_dest)) { |
| 289 | return ETH_PKT_MCAST; |
| 290 | } else { /* unicast */ |
| 291 | return ETH_PKT_UCAST; |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | static inline uint32_t |
| 296 | eth_get_l2_hdr_length(const void *p) |
| 297 | { |
| 298 | uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto); |
| 299 | struct vlan_header *hvlan = PKT_GET_VLAN_HDR(p); |
| 300 | switch (proto) { |
| 301 | case ETH_P_VLAN: |
| 302 | return sizeof(struct eth_header) + sizeof(struct vlan_header); |
| 303 | case ETH_P_DVLAN: |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 304 | if (be16_to_cpu(hvlan->h_proto) == ETH_P_VLAN) { |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 305 | return sizeof(struct eth_header) + 2 * sizeof(struct vlan_header); |
| 306 | } else { |
| 307 | return sizeof(struct eth_header) + sizeof(struct vlan_header); |
| 308 | } |
| 309 | default: |
| 310 | return sizeof(struct eth_header); |
| 311 | } |
| 312 | } |
| 313 | |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 314 | static inline uint32_t |
| 315 | eth_get_l2_hdr_length_iov(const struct iovec *iov, int iovcnt) |
| 316 | { |
| 317 | uint8_t p[sizeof(struct eth_header) + sizeof(struct vlan_header)]; |
| 318 | size_t copied = iov_to_buf(iov, iovcnt, 0, p, ARRAY_SIZE(p)); |
| 319 | |
| 320 | if (copied < ARRAY_SIZE(p)) { |
| 321 | return copied; |
| 322 | } |
| 323 | |
| 324 | return eth_get_l2_hdr_length(p); |
| 325 | } |
| 326 | |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 327 | static inline uint16_t |
| 328 | eth_get_pkt_tci(const void *p) |
| 329 | { |
| 330 | uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto); |
| 331 | struct vlan_header *hvlan = PKT_GET_VLAN_HDR(p); |
| 332 | switch (proto) { |
| 333 | case ETH_P_VLAN: |
| 334 | case ETH_P_DVLAN: |
| 335 | return be16_to_cpu(hvlan->h_tci); |
| 336 | default: |
| 337 | return 0; |
| 338 | } |
| 339 | } |
| 340 | |
Dmitry Fleytman | 566342c | 2017-02-16 14:29:32 +0200 | [diff] [blame] | 341 | size_t |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 342 | eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff, |
| 343 | uint8_t *new_ehdr_buf, |
| 344 | uint16_t *payload_offset, uint16_t *tci); |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 345 | |
Dmitry Fleytman | 566342c | 2017-02-16 14:29:32 +0200 | [diff] [blame] | 346 | size_t |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 347 | eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, |
| 348 | uint16_t vet, uint8_t *new_ehdr_buf, |
| 349 | uint16_t *payload_offset, uint16_t *tci); |
| 350 | |
| 351 | uint16_t |
| 352 | eth_get_l3_proto(const struct iovec *l2hdr_iov, int iovcnt, size_t l2hdr_len); |
| 353 | |
| 354 | void eth_setup_vlan_headers_ex(struct eth_header *ehdr, uint16_t vlan_tag, |
| 355 | uint16_t vlan_ethtype, bool *is_new); |
| 356 | |
| 357 | static inline void |
| 358 | eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, |
| 359 | bool *is_new) |
| 360 | { |
| 361 | eth_setup_vlan_headers_ex(ehdr, vlan_tag, ETH_P_VLAN, is_new); |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 362 | } |
| 363 | |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 364 | |
| 365 | uint8_t eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto); |
| 366 | |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 367 | typedef struct eth_ip6_hdr_info_st { |
| 368 | uint8_t l4proto; |
| 369 | size_t full_hdr_len; |
| 370 | struct ip6_header ip6_hdr; |
| 371 | bool has_ext_hdrs; |
| 372 | bool rss_ex_src_valid; |
| 373 | struct in6_address rss_ex_src; |
| 374 | bool rss_ex_dst_valid; |
| 375 | struct in6_address rss_ex_dst; |
| 376 | bool fragment; |
| 377 | } eth_ip6_hdr_info; |
| 378 | |
| 379 | typedef struct eth_ip4_hdr_info_st { |
| 380 | struct ip_header ip4_hdr; |
| 381 | bool fragment; |
| 382 | } eth_ip4_hdr_info; |
| 383 | |
| 384 | typedef struct eth_l4_hdr_info_st { |
| 385 | union { |
| 386 | struct tcp_header tcp; |
| 387 | struct udp_header udp; |
| 388 | } hdr; |
| 389 | |
| 390 | bool has_tcp_data; |
| 391 | } eth_l4_hdr_info; |
| 392 | |
| 393 | void eth_get_protocols(const struct iovec *iov, int iovcnt, |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 394 | bool *isip4, bool *isip6, |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 395 | bool *isudp, bool *istcp, |
| 396 | size_t *l3hdr_off, |
| 397 | size_t *l4hdr_off, |
| 398 | size_t *l5hdr_off, |
| 399 | eth_ip6_hdr_info *ip6hdr_info, |
| 400 | eth_ip4_hdr_info *ip4hdr_info, |
| 401 | eth_l4_hdr_info *l4hdr_info); |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 402 | |
| 403 | void eth_setup_ip4_fragmentation(const void *l2hdr, size_t l2hdr_len, |
| 404 | void *l3hdr, size_t l3hdr_len, |
| 405 | size_t l3payload_len, |
| 406 | size_t frag_offset, bool more_frags); |
| 407 | |
| 408 | void |
| 409 | eth_fix_ip4_checksum(void *l3hdr, size_t l3hdr_len); |
| 410 | |
| 411 | uint32_t |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 412 | eth_calc_ip4_pseudo_hdr_csum(struct ip_header *iphdr, |
| 413 | uint16_t csl, |
| 414 | uint32_t *cso); |
| 415 | |
| 416 | uint32_t |
| 417 | eth_calc_ip6_pseudo_hdr_csum(struct ip6_header *iphdr, |
| 418 | uint16_t csl, |
| 419 | uint8_t l4_proto, |
| 420 | uint32_t *cso); |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 421 | |
| 422 | bool |
Dmitry Fleytman | eb70002 | 2016-06-01 11:23:41 +0300 | [diff] [blame] | 423 | eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags, |
| 424 | size_t ip6hdr_off, eth_ip6_hdr_info *info); |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 425 | |
Bin Meng | af77451 | 2021-03-17 14:26:27 +0800 | [diff] [blame] | 426 | /** |
| 427 | * eth_pad_short_frame - pad a short frame to the minimum Ethernet frame length |
| 428 | * |
| 429 | * If the Ethernet frame size is shorter than 60 bytes, it will be padded to |
| 430 | * 60 bytes at the address @padded_pkt. |
| 431 | * |
| 432 | * @padded_pkt: buffer address to hold the padded frame |
| 433 | * @padded_buflen: pointer holding length of @padded_pkt. If the frame is |
| 434 | * padded, the length will be updated to the padded one. |
| 435 | * @pkt: address to hold the original Ethernet frame |
| 436 | * @pkt_size: size of the original Ethernet frame |
| 437 | * @return true if the frame is padded, otherwise false |
| 438 | */ |
| 439 | bool eth_pad_short_frame(uint8_t *padded_pkt, size_t *padded_buflen, |
| 440 | const void *pkt, size_t pkt_size); |
| 441 | |
Dmitry Fleytman | 75020a7 | 2013-03-09 11:21:04 +0200 | [diff] [blame] | 442 | #endif |