/*
- * 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.
#include "util.h"
struct ofpbuf;
+struct ds;
bool dpid_from_string(const char *s, uint64_t *dpidp);
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;
{
/* 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])
{
uint16_t snap_type,
const uint8_t eth_src[ETH_ADDR_LEN]);
+void eth_push_vlan(struct ofpbuf *, ovs_be16 tci);
+
/* Example:
*
* uint8_t mac[ETH_ADDR_LEN];
#define ETH_TYPE_IP 0x0800
#define ETH_TYPE_ARP 0x0806
#define ETH_TYPE_VLAN 0x8100
-#define ETH_TYPE_CFM 0x8902
+#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. */
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));
#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));
/* 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(uint16_t vlan_tci)
+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(uint16_t vlan_tci)
+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));
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));
-/* A 'ccm' represents a Continuity Check Message from the 802.1ag specification.
- * Continuity Check Messages are broadcast periodically so that hosts can
- * determine who they have connectivity to. */
-#define CCM_LEN 74
-#define CCM_MAID_LEN 48
-struct ccm {
- uint8_t mdlevel_version; /* MD Level and Version */
- uint8_t opcode;
- uint8_t flags;
- uint8_t tlv_offset;
- uint32_t seq;
- uint16_t mpid;
- uint8_t maid[CCM_MAID_LEN];
- uint8_t zero[16]; /* Defined by ITU-T Y.1731 should be zero */
-} __attribute__((packed));
-BUILD_ASSERT_DECL(CCM_LEN == sizeof(struct ccm));
-
/* The "(void) (ip)[0]" below has no effect on the value, since it's the first
* argument of a comma expression, but it makes sure that 'ip' is a pointer.
* This is useful since a common mistake is to pass an integer instead of a
((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
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));
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));
#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));
#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 */