X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fpackets.h;h=a389e6af74ff500a21612c6c98f47ddecc5bc1a8;hb=0697b5c3c9954057028f406757c4fd0208b929b9;hp=fb044071780624ec8889131e900d3e74251b0873;hpb=d295e8e97acae13552a5b220d3fbcff8201064a2;p=sliver-openvswitch.git diff --git a/lib/packets.h b/lib/packets.h index fb0440717..a389e6af7 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,13 +18,17 @@ #define PACKETS_H 1 #include +#include +#include #include #include #include "compiler.h" +#include "openvswitch/types.h" #include "random.h" #include "util.h" struct ofpbuf; +struct ds; bool dpid_from_string(const char *s, uint64_t *dpidp); @@ -36,6 +40,9 @@ static const uint8_t eth_addr_broadcast[ETH_ADDR_LEN] OVS_UNUSED static const uint8_t eth_addr_stp[ETH_ADDR_LEN] OVS_UNUSED = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x01 }; +static const uint8_t eth_addr_lacp[ETH_ADDR_LEN] OVS_UNUSED + = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }; + static inline bool eth_addr_is_broadcast(const uint8_t ea[6]) { return (ea[0] & ea[1] & ea[2] & ea[3] & ea[4] & ea[5]) == 0xff; @@ -49,17 +56,22 @@ static inline bool eth_addr_is_local(const uint8_t ea[6]) { /* Local if it is either a locally administered address or a Nicira random * address. */ - return !!(ea[0] & 2) - || (ea[0] == 0x00 && ea[1] == 0x23 && ea[2] == 0x20 && !!(ea[3] & 0x80)); + return ea[0] & 2 + || (ea[0] == 0x00 && ea[1] == 0x23 && ea[2] == 0x20 && ea[3] & 0x80); } static inline bool eth_addr_is_zero(const uint8_t ea[6]) { return !(ea[0] | ea[1] | ea[2] | ea[3] | ea[4] | ea[5]); } +static inline int eth_addr_compare_3way(const uint8_t a[ETH_ADDR_LEN], + const uint8_t b[ETH_ADDR_LEN]) +{ + return memcmp(a, b, ETH_ADDR_LEN); +} static inline bool eth_addr_equals(const uint8_t a[ETH_ADDR_LEN], const uint8_t b[ETH_ADDR_LEN]) { - return !memcmp(a, b, ETH_ADDR_LEN); + return !eth_addr_compare_3way(a, b); } static inline uint64_t eth_addr_to_uint64(const uint8_t ea[ETH_ADDR_LEN]) { @@ -119,6 +131,8 @@ void compose_benign_packet(struct ofpbuf *, const char *tag, uint16_t snap_type, const uint8_t eth_src[ETH_ADDR_LEN]); +void eth_set_vlan_tci(struct ofpbuf *, ovs_be16 tci); + /* Example: * * uint8_t mac[ETH_ADDR_LEN]; @@ -150,6 +164,12 @@ void compose_benign_packet(struct ofpbuf *, const char *tag, #define ETH_TYPE_IP 0x0800 #define ETH_TYPE_ARP 0x0806 #define ETH_TYPE_VLAN 0x8100 +#define ETH_TYPE_IPV6 0x86dd +#define ETH_TYPE_LACP 0x8809 + +/* Minimum value for an Ethernet type. Values below this are IEEE 802.2 frame + * lengths. */ +#define ETH_TYPE_MIN 0x600 #define ETH_HEADER_LEN 14 #define ETH_PAYLOAD_MIN 46 @@ -160,7 +180,7 @@ void compose_benign_packet(struct ofpbuf *, const char *tag, struct eth_header { uint8_t eth_dst[ETH_ADDR_LEN]; uint8_t eth_src[ETH_ADDR_LEN]; - uint16_t eth_type; + ovs_be16 eth_type; } __attribute__((packed)); BUILD_ASSERT_DECL(ETH_HEADER_LEN == sizeof(struct eth_header)); @@ -181,7 +201,7 @@ BUILD_ASSERT_DECL(LLC_HEADER_LEN == sizeof(struct llc_header)); #define SNAP_HEADER_LEN 5 struct snap_header { uint8_t snap_org[3]; - uint16_t snap_type; + ovs_be16 snap_type; } __attribute__((packed)); BUILD_ASSERT_DECL(SNAP_HEADER_LEN == sizeof(struct snap_header)); @@ -198,10 +218,28 @@ BUILD_ASSERT_DECL(LLC_SNAP_HEADER_LEN == sizeof(struct llc_snap_header)); #define VLAN_PCP_MASK 0xe000 #define VLAN_PCP_SHIFT 13 +#define VLAN_CFI 0x1000 + +/* Given the vlan_tci field from an 802.1Q header, in network byte order, + * returns the VLAN ID in host byte order. */ +static inline uint16_t +vlan_tci_to_vid(ovs_be16 vlan_tci) +{ + return (ntohs(vlan_tci) & VLAN_VID_MASK) >> VLAN_VID_SHIFT; +} + +/* Given the vlan_tci field from an 802.1Q header, in network byte order, + * returns the priority code point (PCP) in host byte order. */ +static inline int +vlan_tci_to_pcp(ovs_be16 vlan_tci) +{ + return (ntohs(vlan_tci) & VLAN_PCP_MASK) >> VLAN_PCP_SHIFT; +} + #define VLAN_HEADER_LEN 4 struct vlan_header { - uint16_t vlan_tci; /* Lowest 12 bits are VLAN ID. */ - uint16_t vlan_next_type; + ovs_be16 vlan_tci; /* Lowest 12 bits are VLAN ID. */ + ovs_be16 vlan_next_type; }; BUILD_ASSERT_DECL(VLAN_HEADER_LEN == sizeof(struct vlan_header)); @@ -209,9 +247,9 @@ BUILD_ASSERT_DECL(VLAN_HEADER_LEN == sizeof(struct vlan_header)); struct vlan_eth_header { uint8_t veth_dst[ETH_ADDR_LEN]; uint8_t veth_src[ETH_ADDR_LEN]; - uint16_t veth_type; /* Always htons(ETH_TYPE_VLAN). */ - uint16_t veth_tci; /* Lowest 12 bits are VLAN ID. */ - uint16_t veth_next_type; + ovs_be16 veth_type; /* Always htons(ETH_TYPE_VLAN). */ + ovs_be16 veth_tci; /* Lowest 12 bits are VLAN ID. */ + ovs_be16 veth_next_type; } __attribute__((packed)); BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header)); @@ -226,6 +264,34 @@ BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header)); ((uint8_t *) ip)[2], \ ((uint8_t *) ip)[3] +/* Example: + * + * char *string = "1 33.44.55.66 2"; + * ovs_be32 ip; + * int a, b; + * + * if (sscanf(string, "%d"IP_SCAN_FMT"%d", + * &a, IP_SCAN_ARGS(&ip), &b) == 1 + IP_SCAN_COUNT + 1) { + * ... + * } + */ +#define IP_SCAN_FMT "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8 +#define IP_SCAN_ARGS(ip) \ + ((void) (ovs_be32) *(ip), &((uint8_t *) ip)[0]), \ + &((uint8_t *) ip)[1], \ + &((uint8_t *) ip)[2], \ + &((uint8_t *) ip)[3] +#define IP_SCAN_COUNT 4 + +/* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N + * high-order 1-bits and 32-N low-order 0-bits. */ +static inline bool +ip_is_cidr(ovs_be32 netmask) +{ + uint32_t x = ~ntohl(netmask); + return !(x & (x + 1)); +} + #define IP_VER(ip_ihl_ver) ((ip_ihl_ver) >> 4) #define IP_IHL(ip_ihl_ver) ((ip_ihl_ver) & 15) #define IP_IHL_VER(ihl, ver) (((ver) << 4) | (ihl)) @@ -234,10 +300,6 @@ BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header)); #define IP_ECN_MASK 0x03 #define IP_DSCP_MASK 0xfc -#define IP_TYPE_ICMP 1 -#define IP_TYPE_TCP 6 -#define IP_TYPE_UDP 17 - #define IP_VERSION 4 #define IP_DONT_FRAGMENT 0x4000 /* Don't fragment. */ @@ -250,14 +312,14 @@ BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header)); struct ip_header { uint8_t ip_ihl_ver; uint8_t ip_tos; - uint16_t ip_tot_len; - uint16_t ip_id; - uint16_t ip_frag_off; + ovs_be16 ip_tot_len; + ovs_be16 ip_id; + ovs_be16 ip_frag_off; uint8_t ip_ttl; uint8_t ip_proto; - uint16_t ip_csum; - uint32_t ip_src; - uint32_t ip_dst; + ovs_be16 ip_csum; + ovs_be32 ip_src; + ovs_be32 ip_dst; }; BUILD_ASSERT_DECL(IP_HEADER_LEN == sizeof(struct ip_header)); @@ -265,16 +327,16 @@ BUILD_ASSERT_DECL(IP_HEADER_LEN == sizeof(struct ip_header)); struct icmp_header { uint8_t icmp_type; uint8_t icmp_code; - uint16_t icmp_csum; + ovs_be16 icmp_csum; }; BUILD_ASSERT_DECL(ICMP_HEADER_LEN == sizeof(struct icmp_header)); #define UDP_HEADER_LEN 8 struct udp_header { - uint16_t udp_src; - uint16_t udp_dst; - uint16_t udp_len; - uint16_t udp_csum; + ovs_be16 udp_src; + ovs_be16 udp_dst; + ovs_be16 udp_len; + ovs_be16 udp_csum; }; BUILD_ASSERT_DECL(UDP_HEADER_LEN == sizeof(struct udp_header)); @@ -285,19 +347,19 @@ BUILD_ASSERT_DECL(UDP_HEADER_LEN == sizeof(struct udp_header)); #define TCP_ACK 0x10 #define TCP_URG 0x20 -#define TCP_FLAGS(tcp_ctl) (htons(tcp_ctl) & 0x003f) -#define TCP_OFFSET(tcp_ctl) (htons(tcp_ctl) >> 12) +#define TCP_FLAGS(tcp_ctl) (ntohs(tcp_ctl) & 0x003f) +#define TCP_OFFSET(tcp_ctl) (ntohs(tcp_ctl) >> 12) #define TCP_HEADER_LEN 20 struct tcp_header { - uint16_t tcp_src; - uint16_t tcp_dst; - uint32_t tcp_seq; - uint32_t tcp_ack; - uint16_t tcp_ctl; - uint16_t tcp_winsz; - uint16_t tcp_csum; - uint16_t tcp_urg; + ovs_be16 tcp_src; + ovs_be16 tcp_dst; + ovs_be32 tcp_seq; + ovs_be32 tcp_ack; + ovs_be16 tcp_ctl; + ovs_be16 tcp_winsz; + ovs_be16 tcp_csum; + ovs_be16 tcp_urg; }; BUILD_ASSERT_DECL(TCP_HEADER_LEN == sizeof(struct tcp_header)); @@ -309,18 +371,69 @@ BUILD_ASSERT_DECL(TCP_HEADER_LEN == sizeof(struct tcp_header)); #define ARP_ETH_HEADER_LEN 28 struct arp_eth_header { /* Generic members. */ - uint16_t ar_hrd; /* Hardware type. */ - uint16_t ar_pro; /* Protocol type. */ + ovs_be16 ar_hrd; /* Hardware type. */ + ovs_be16 ar_pro; /* Protocol type. */ uint8_t ar_hln; /* Hardware address length. */ uint8_t ar_pln; /* Protocol address length. */ - uint16_t ar_op; /* Opcode. */ + ovs_be16 ar_op; /* Opcode. */ /* Ethernet+IPv4 specific members. */ uint8_t ar_sha[ETH_ADDR_LEN]; /* Sender hardware address. */ - uint32_t ar_spa; /* Sender protocol address. */ + ovs_be32 ar_spa; /* Sender protocol address. */ uint8_t ar_tha[ETH_ADDR_LEN]; /* Target hardware address. */ - uint32_t ar_tpa; /* Target protocol address. */ + ovs_be32 ar_tpa; /* Target protocol address. */ } __attribute__((packed)); BUILD_ASSERT_DECL(ARP_ETH_HEADER_LEN == sizeof(struct arp_eth_header)); +/* Example: + * + * char *string = "1 ::1 2"; + * char ipv6_s[IPV6_SCAN_LEN + 1]; + * struct in6_addr ipv6; + * + * if (sscanf(string, "%d"IPV6_SCAN_FMT"%d", &a, ipv6_s, &b) == 3 + * && inet_pton(AF_INET6, ipv6_s, &ipv6) == 1) { + * ... + * } + */ +#define IPV6_SCAN_FMT "%46[0123456789abcdefABCDEF:.]" +#define IPV6_SCAN_LEN 46 + +extern const struct in6_addr in6addr_exact; +#define IN6ADDR_EXACT_INIT { { { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, \ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } } } + +static inline bool ipv6_addr_equals(const struct in6_addr *a, + const struct in6_addr *b) +{ +#ifdef IN6_ARE_ADDR_EQUAL + return IN6_ARE_ADDR_EQUAL(a, b); +#else + return !memcmp(a, b, sizeof(*a)); +#endif +} + +static inline bool ipv6_mask_is_any(const struct in6_addr *mask) { + return ipv6_addr_equals(mask, &in6addr_any); +} + +static inline bool ipv6_mask_is_exact(const struct in6_addr *mask) { + return ipv6_addr_equals(mask, &in6addr_exact); +} + +void format_ipv6_addr(char *addr_str, const struct in6_addr *addr); +void print_ipv6_addr(struct ds *string, const struct in6_addr *addr); +struct in6_addr ipv6_addr_bitand(const struct in6_addr *src, + const struct in6_addr *mask); +struct in6_addr ipv6_create_mask(int mask); +int ipv6_count_cidr_bits(const struct in6_addr *netmask); +bool ipv6_is_cidr(const struct in6_addr *netmask); + +void *eth_compose(struct ofpbuf *, const uint8_t eth_dst[ETH_ADDR_LEN], + const uint8_t eth_src[ETH_ADDR_LEN], uint16_t eth_type, + size_t size); +void *snap_compose(struct ofpbuf *, const uint8_t eth_dst[ETH_ADDR_LEN], + const uint8_t eth_src[ETH_ADDR_LEN], + unsigned int oui, uint16_t snap_type, size_t size); + #endif /* packets.h */