diff options
Diffstat (limited to 'include/net')
| -rw-r--r-- | include/net/checksum.h | 49 | ||||
| -rw-r--r-- | include/net/eth.h | 158 | ||||
| -rw-r--r-- | include/net/net.h | 19 |
3 files changed, 181 insertions, 45 deletions
diff --git a/include/net/checksum.h b/include/net/checksum.h index 7de1acb79a..7df472c2fe 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h @@ -18,6 +18,7 @@ #ifndef QEMU_NET_CHECKSUM_H #define QEMU_NET_CHECKSUM_H +#include "qemu/bswap.h" struct iovec; uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq); @@ -45,9 +46,55 @@ net_raw_checksum(uint8_t *data, int length) * @iov_cnt: number of array elements * @iov_off: starting iov offset for checksumming * @size: length of data to be checksummed + * @csum_offset: offset of the checksum chunk */ uint32_t net_checksum_add_iov(const struct iovec *iov, const unsigned int iov_cnt, - uint32_t iov_off, uint32_t size); + uint32_t iov_off, uint32_t size, + uint32_t csum_offset); + +typedef struct toeplitz_key_st { + uint32_t leftmost_32_bits; + uint8_t *next_byte; +} net_toeplitz_key; + +static inline +void net_toeplitz_key_init(net_toeplitz_key *key, uint8_t *key_bytes) +{ + key->leftmost_32_bits = be32_to_cpu(*(uint32_t *)key_bytes); + key->next_byte = key_bytes + sizeof(uint32_t); +} + +static inline +void net_toeplitz_add(uint32_t *result, + uint8_t *input, + uint32_t len, + net_toeplitz_key *key) +{ + register uint32_t accumulator = *result; + register uint32_t leftmost_32_bits = key->leftmost_32_bits; + register uint32_t byte; + + for (byte = 0; byte < len; byte++) { + register uint8_t input_byte = input[byte]; + register uint8_t key_byte = *(key->next_byte++); + register uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (input_byte & (1 << 7)) { + accumulator ^= leftmost_32_bits; + } + + leftmost_32_bits = + (leftmost_32_bits << 1) | ((key_byte & (1 << 7)) >> 7); + + input_byte <<= 1; + key_byte <<= 1; + } + } + + key->leftmost_32_bits = leftmost_32_bits; + *result = accumulator; +} #endif /* QEMU_NET_CHECKSUM_H */ diff --git a/include/net/eth.h b/include/net/eth.h index 18d0be3b16..2013175857 100644 --- a/include/net/eth.h +++ b/include/net/eth.h @@ -67,6 +67,16 @@ typedef struct tcp_header { uint16_t th_urp; /* urgent pointer */ } tcp_header; +#define TCP_FLAGS_ONLY(flags) ((flags) & 0x3f) + +#define TCP_HEADER_FLAGS(tcp) \ + TCP_FLAGS_ONLY(be16_to_cpu((tcp)->th_offset_flags)) + +#define TCP_FLAG_ACK 0x10 + +#define TCP_HEADER_DATA_OFFSET(tcp) \ + (((be16_to_cpu((tcp)->th_offset_flags) >> 12) & 0xf) << 2) + typedef struct udp_header { uint16_t uh_sport; /* source port */ uint16_t uh_dport; /* destination port */ @@ -108,11 +118,34 @@ struct ip6_header { struct in6_address ip6_dst; /* destination address */ }; +typedef struct ip6_pseudo_header { + struct in6_address ip6_src; + struct in6_address ip6_dst; + uint32_t len; + uint8_t zero[3]; + uint8_t next_hdr; +} ip6_pseudo_header; + struct ip6_ext_hdr { uint8_t ip6r_nxt; /* next header */ uint8_t ip6r_len; /* length in units of 8 octets */ }; +struct ip6_ext_hdr_routing { + uint8_t nxt; + uint8_t len; + uint8_t rtype; + uint8_t segleft; + uint8_t rsvd[4]; +}; + +struct ip6_option_hdr { +#define IP6_OPT_PAD1 (0x00) +#define IP6_OPT_HOME (0xC9) + uint8_t type; + uint8_t len; +}; + struct udp_hdr { uint16_t uh_sport; /* source port */ uint16_t uh_dport; /* destination port */ @@ -161,19 +194,22 @@ struct tcp_hdr { #define PKT_GET_IP_HDR(p) \ ((struct ip_header *)(((uint8_t *)(p)) + eth_get_l2_hdr_length(p))) #define IP_HDR_GET_LEN(p) \ - ((((struct ip_header *)p)->ip_ver_len & 0x0F) << 2) + ((((struct ip_header *)(p))->ip_ver_len & 0x0F) << 2) #define PKT_GET_IP_HDR_LEN(p) \ (IP_HDR_GET_LEN(PKT_GET_IP_HDR(p))) #define PKT_GET_IP6_HDR(p) \ ((struct ip6_header *) (((uint8_t *)(p)) + eth_get_l2_hdr_length(p))) #define IP_HEADER_VERSION(ip) \ - ((ip->ip_ver_len >> 4)&0xf) + (((ip)->ip_ver_len >> 4) & 0xf) +#define IP4_IS_FRAGMENT(ip) \ + ((be16_to_cpu((ip)->ip_off) & (IP_OFFMASK | IP_MF)) != 0) #define ETH_P_IP (0x0800) /* Internet Protocol packet */ #define ETH_P_ARP (0x0806) /* Address Resolution packet */ #define ETH_P_IPV6 (0x86dd) #define ETH_P_VLAN (0x8100) #define ETH_P_DVLAN (0x88a8) +#define ETH_P_UNKNOWN (0xffff) #define VLAN_VID_MASK 0x0fff #define IP_HEADER_VERSION_4 (4) #define IP_HEADER_VERSION_6 (6) @@ -258,7 +294,7 @@ eth_get_l2_hdr_length(const void *p) case ETH_P_VLAN: return sizeof(struct eth_header) + sizeof(struct vlan_header); case ETH_P_DVLAN: - if (hvlan->h_proto == ETH_P_VLAN) { + if (be16_to_cpu(hvlan->h_proto) == ETH_P_VLAN) { return sizeof(struct eth_header) + 2 * sizeof(struct vlan_header); } else { return sizeof(struct eth_header) + sizeof(struct vlan_header); @@ -268,6 +304,19 @@ eth_get_l2_hdr_length(const void *p) } } +static inline uint32_t +eth_get_l2_hdr_length_iov(const struct iovec *iov, int iovcnt) +{ + uint8_t p[sizeof(struct eth_header) + sizeof(struct vlan_header)]; + size_t copied = iov_to_buf(iov, iovcnt, 0, p, ARRAY_SIZE(p)); + + if (copied < ARRAY_SIZE(p)) { + return copied; + } + + return eth_get_l2_hdr_length(p); +} + static inline uint16_t eth_get_pkt_tci(const void *p) { @@ -282,51 +331,67 @@ eth_get_pkt_tci(const void *p) } } -static inline bool -eth_strip_vlan(const void *p, uint8_t *new_ehdr_buf, - uint16_t *payload_offset, uint16_t *tci) -{ - uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto); - struct vlan_header *hvlan = PKT_GET_VLAN_HDR(p); - struct eth_header *new_ehdr = (struct eth_header *) new_ehdr_buf; +bool +eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff, + uint8_t *new_ehdr_buf, + uint16_t *payload_offset, uint16_t *tci); - switch (proto) { - case ETH_P_VLAN: - case ETH_P_DVLAN: - memcpy(new_ehdr->h_source, PKT_GET_ETH_HDR(p)->h_source, ETH_ALEN); - memcpy(new_ehdr->h_dest, PKT_GET_ETH_HDR(p)->h_dest, ETH_ALEN); - new_ehdr->h_proto = hvlan->h_proto; - *tci = be16_to_cpu(hvlan->h_tci); - *payload_offset = - sizeof(struct eth_header) + sizeof(struct vlan_header); - if (be16_to_cpu(new_ehdr->h_proto) == ETH_P_VLAN) { - memcpy(PKT_GET_VLAN_HDR(new_ehdr), - PKT_GET_DVLAN_HDR(p), - sizeof(struct vlan_header)); - *payload_offset += sizeof(struct vlan_header); - } - return true; - default: - return false; - } -} +bool +eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, + uint16_t vet, uint8_t *new_ehdr_buf, + uint16_t *payload_offset, uint16_t *tci); -static inline uint16_t -eth_get_l3_proto(const void *l2hdr, size_t l2hdr_len) +uint16_t +eth_get_l3_proto(const struct iovec *l2hdr_iov, int iovcnt, size_t l2hdr_len); + +void eth_setup_vlan_headers_ex(struct eth_header *ehdr, uint16_t vlan_tag, + uint16_t vlan_ethtype, bool *is_new); + +static inline void +eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, + bool *is_new) { - uint8_t *proto_ptr = (uint8_t *) l2hdr + l2hdr_len - sizeof(uint16_t); - return be16_to_cpup((uint16_t *)proto_ptr); + eth_setup_vlan_headers_ex(ehdr, vlan_tag, ETH_P_VLAN, is_new); } -void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, - bool *is_new); uint8_t eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto); -void eth_get_protocols(const uint8_t *headers, - uint32_t hdr_length, +typedef struct eth_ip6_hdr_info_st { + uint8_t l4proto; + size_t full_hdr_len; + struct ip6_header ip6_hdr; + bool has_ext_hdrs; + bool rss_ex_src_valid; + struct in6_address rss_ex_src; + bool rss_ex_dst_valid; + struct in6_address rss_ex_dst; + bool fragment; +} eth_ip6_hdr_info; + +typedef struct eth_ip4_hdr_info_st { + struct ip_header ip4_hdr; + bool fragment; +} eth_ip4_hdr_info; + +typedef struct eth_l4_hdr_info_st { + union { + struct tcp_header tcp; + struct udp_header udp; + } hdr; + + bool has_tcp_data; +} eth_l4_hdr_info; + +void eth_get_protocols(const struct iovec *iov, int iovcnt, bool *isip4, bool *isip6, - bool *isudp, bool *istcp); + bool *isudp, bool *istcp, + size_t *l3hdr_off, + size_t *l4hdr_off, + size_t *l5hdr_off, + eth_ip6_hdr_info *ip6hdr_info, + eth_ip4_hdr_info *ip4hdr_info, + eth_l4_hdr_info *l4hdr_info); void eth_setup_ip4_fragmentation(const void *l2hdr, size_t l2hdr_len, void *l3hdr, size_t l3hdr_len, @@ -337,11 +402,18 @@ void eth_fix_ip4_checksum(void *l3hdr, size_t l3hdr_len); uint32_t -eth_calc_pseudo_hdr_csum(struct ip_header *iphdr, uint16_t csl); +eth_calc_ip4_pseudo_hdr_csum(struct ip_header *iphdr, + uint16_t csl, + uint32_t *cso); + +uint32_t +eth_calc_ip6_pseudo_hdr_csum(struct ip6_header *iphdr, + uint16_t csl, + uint8_t l4_proto, + uint32_t *cso); bool -eth_parse_ipv6_hdr(struct iovec *pkt, int pkt_frags, - size_t ip6hdr_off, uint8_t *l4proto, - size_t *full_hdr_len); +eth_parse_ipv6_hdr(const struct iovec *pkt, int pkt_frags, + size_t ip6hdr_off, eth_ip6_hdr_info *info); #endif diff --git a/include/net/net.h b/include/net/net.h index 73e4c466e2..a69e382ba7 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -9,6 +9,11 @@ #include "migration/vmstate.h" #include "qapi-types.h" +#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X" +#define MAC_ARG(x) ((uint8_t *)(x))[0], ((uint8_t *)(x))[1], \ + ((uint8_t *)(x))[2], ((uint8_t *)(x))[3], \ + ((uint8_t *)(x))[4], ((uint8_t *)(x))[5] + #define MAX_QUEUE_NUM 1024 /* Maximum GSO packet size (64k) plus plenty of room for @@ -57,6 +62,8 @@ typedef void (SetOffload)(NetClientState *, int, int, int, int, int); typedef void (SetVnetHdrLen)(NetClientState *, int); typedef int (SetVnetLE)(NetClientState *, bool); typedef int (SetVnetBE)(NetClientState *, bool); +typedef struct SocketReadState SocketReadState; +typedef void (SocketReadStateFinalize)(SocketReadState *rs); typedef struct NetClientInfo { NetClientOptionsKind type; @@ -102,6 +109,15 @@ typedef struct NICState { bool peer_deleted; } NICState; +struct SocketReadState { + int state; /* 0 = getting length, 1 = getting data */ + uint32_t index; + uint32_t packet_len; + uint8_t buf[NET_BUFSIZE]; + SocketReadStateFinalize *finalize; +}; + +int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size); char *qemu_mac_strdup_printf(const uint8_t *macaddr); NetClientState *qemu_find_netdev(const char *id); int qemu_find_net_clients_except(const char *id, NetClientState **ncs, @@ -160,6 +176,8 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender, void print_net_client(Monitor *mon, NetClientState *nc); void hmp_info_network(Monitor *mon, const QDict *qdict); +void net_socket_rs_init(SocketReadState *rs, + SocketReadStateFinalize *finalize); /* NIC info */ @@ -178,7 +196,6 @@ struct NICInfo { extern int nb_nics; extern NICInfo nd_table[MAX_NICS]; -extern int default_net; extern const char *host_net_devices[]; /* from net.c */ |