Reid Price reid@nicira.com
Romain Lenglet romain.lenglet@berabera.info
Sajjad Lateef slateef@nicira.com
+Shih-Hao Li shli@nicira.com
Simon Horman horms@verge.net.au
Tetsuo NAKAGAWA nakagawa@mxc.nes.nec.co.jp
Thomas Lacroix thomas.lacroix@citrix.com
AC_MSG_ERROR([This appears to be XenServer $ovs_cv_xsversion, but only XenServer 5.6.100 or later is supported. (If you are really using a supported version of XenServer, you may override this error message by specifying 'ovs_cv_xsversion=5.6.100' on the "configure" command line.)])
;;
esac])
+
+dnl OVS_MAKE_HAS_IF([if-true], [if-false])
+dnl
+dnl Checks whether make has the GNU make $(if condition,then,else) extension.
+dnl Runs 'if-true' if so, 'if-false' otherwise.
+AC_DEFUN([OVS_MAKE_HAS_IF],
+ [AC_CACHE_CHECK(
+ [whether ${MAKE-make} has GNU make \$(if) extension],
+ [ovs_cv_gnu_make_if],
+ [cat <<'EOF' > conftest.mk
+conftest.out:
+ echo $(if x,y,z) > conftest.out
+.PHONY: all
+EOF
+ rm -f conftest.out
+ AS_ECHO(["$as_me:$LINENO: invoking ${MAKE-make} -f conftest.mk all:"]) >&AS_MESSAGE_LOG_FD 2>&1
+ ${MAKE-make} -f conftest.mk conftest.out >&AS_MESSAGE_LOG_FD 2>&1
+ AS_ECHO(["$as_me:$LINENO: conftest.out contains:"]) >&AS_MESSAGE_LOG_FD 2>&1
+ cat conftest.out >&AS_MESSAGE_LOG_FD 2>&1
+ result=`cat conftest.out`
+ rm -f conftest.mk conftest.out
+ if test "X$result" = "Xy"; then
+ ovs_cv_gnu_make_if=yes
+ else
+ ovs_cv_gnu_make_if=no
+ fi])
+ AS_IF([test $ovs_cv_gnu_make_if = yes], [$1], [$2])])
+
+dnl OVS_ENABLE_SPARSE
+AC_DEFUN([OVS_ENABLE_SPARSE],
+ [OVS_MAKE_HAS_IF(
+ [AC_CONFIG_COMMANDS_PRE(
+ [: ${SPARSE=sparse}
+ AC_SUBST([SPARSE])
+ CC='$(if $(C),REAL_CC="'"$CC"'" CHECK="$(SPARSE) -I $(top_srcdir)/include/sparse" cgcc,'"$CC"')'])])])
OVS_CHECK_PKIDIR
OVS_CHECK_RUNDIR
+OVS_CHECK_BACKTRACE
OVS_CHECK_MALLOC_HOOKS
OVS_CHECK_VALGRIND
OVS_CHECK_SOCKET_LIBS
OVS_CONDITIONAL_CC_OPTION([-Wno-unused], [HAVE_WNO_UNUSED])
OVS_CONDITIONAL_CC_OPTION([-Wno-unused-parameter], [HAVE_WNO_UNUSED_PARAMETER])
OVS_ENABLE_WERROR
+OVS_ENABLE_SPARSE
AC_ARG_VAR(KARCH, [Kernel Architecture String])
AC_SUBST(KARCH)
static bool is_ip(struct sk_buff *skb)
{
- return (OVS_CB(skb)->flow->key.dl_type == htons(ETH_P_IP) &&
+ return (OVS_CB(skb)->flow->key.eth.type == htons(ETH_P_IP) &&
skb->transport_header > skb->network_header);
}
static __sum16 *get_l4_checksum(struct sk_buff *skb)
{
- u8 nw_proto = OVS_CB(skb)->flow->key.nw_proto;
+ u8 nw_proto = OVS_CB(skb)->flow->key.ip.nw_proto;
int transport_len = skb->len - skb_transport_offset(skb);
if (nw_proto == IPPROTO_TCP) {
if (likely(transport_len >= sizeof(struct tcphdr)))
{
struct arp_eth_header *arp;
- if (OVS_CB(skb)->flow->key.dl_type != htons(ETH_P_ARP))
+ if (OVS_CB(skb)->flow->key.eth.type != htons(ETH_P_ARP))
return false;
if (skb_network_offset(skb) + sizeof(struct arp_eth_header) > skb->len)
if (!OVS_CB(skb)->flow) {
struct sw_flow_key key;
struct tbl_node *flow_node;
+ int key_len;
bool is_frag;
/* Extract flow from 'skb' into 'key'. */
- error = flow_extract(skb, p->port_no, &key, &is_frag);
+ error = flow_extract(skb, p->port_no, &key, &key_len, &is_frag);
if (unlikely(error)) {
kfree_skb(skb);
return;
}
/* Look up flow. */
- flow_node = tbl_lookup(rcu_dereference(dp->table), &key,
- flow_hash(&key), flow_cmp);
+ flow_node = tbl_lookup(rcu_dereference(dp->table), &key, key_len,
+ flow_hash(&key, key_len), flow_cmp);
if (unlikely(!flow_node)) {
struct dp_upcall_info upcall;
bool is_frag;
int len;
int err;
+ int key_len;
err = -EINVAL;
if (!a[ODP_PACKET_ATTR_PACKET] || !a[ODP_PACKET_ATTR_ACTIONS] ||
if (IS_ERR(flow))
goto err_kfree_skb;
- err = flow_extract(packet, -1, &flow->key, &is_frag);
+ err = flow_extract(packet, -1, &flow->key, &key_len, &is_frag);
if (err)
goto err_flow_put;
- flow->tbl_node.hash = flow_hash(&flow->key);
+ flow->tbl_node.hash = flow_hash(&flow->key, key_len);
acts = flow_actions_alloc(a[ODP_PACKET_ATTR_ACTIONS]);
err = PTR_ERR(acts);
struct tbl *table;
u32 hash;
int error;
+ int key_len;
/* Extract key. */
error = -EINVAL;
if (!a[ODP_FLOW_ATTR_KEY])
goto error;
- error = flow_from_nlattrs(&key, a[ODP_FLOW_ATTR_KEY]);
+ error = flow_from_nlattrs(&key, &key_len, a[ODP_FLOW_ATTR_KEY]);
if (error)
goto error;
if (!dp)
goto error;
- hash = flow_hash(&key);
+ hash = flow_hash(&key, key_len);
table = get_table_protected(dp);
- flow_node = tbl_lookup(table, &key, hash, flow_cmp);
+ flow_node = tbl_lookup(table, &key, key_len, hash, flow_cmp);
if (!flow_node) {
struct sw_flow_actions *acts;
struct datapath *dp;
struct tbl *table;
int err;
+ int key_len;
if (!a[ODP_FLOW_ATTR_KEY])
return -EINVAL;
- err = flow_from_nlattrs(&key, a[ODP_FLOW_ATTR_KEY]);
+ err = flow_from_nlattrs(&key, &key_len, a[ODP_FLOW_ATTR_KEY]);
if (err)
return err;
return -ENODEV;
table = get_table_protected(dp);
- flow_node = tbl_lookup(table, &key, flow_hash(&key), flow_cmp);
+ flow_node = tbl_lookup(table, &key, key_len, flow_hash(&key, key_len),
+ flow_cmp);
if (!flow_node)
return -ENOENT;
struct datapath *dp;
struct tbl *table;
int err;
+ int key_len;
if (!a[ODP_FLOW_ATTR_KEY])
return flush_flows(odp_header->dp_ifindex);
- err = flow_from_nlattrs(&key, a[ODP_FLOW_ATTR_KEY]);
+ err = flow_from_nlattrs(&key, &key_len, a[ODP_FLOW_ATTR_KEY]);
if (err)
return err;
return -ENODEV;
table = get_table_protected(dp);
- flow_node = tbl_lookup(table, &key, flow_hash(&key), flow_cmp);
+ flow_node = tbl_lookup(table, &key, key_len, flow_hash(&key, key_len),
+ flow_cmp);
if (!flow_node)
return -ENOENT;
flow = flow_cast(flow_node);
return cur_ms - idle_ms;
}
-static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
+#define SW_FLOW_KEY_OFFSET(field) \
+ offsetof(struct sw_flow_key, field) + \
+ FIELD_SIZEOF(struct sw_flow_key, field)
+
+static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key,
+ int *key_lenp)
{
unsigned int nh_ofs = skb_network_offset(skb);
unsigned int nh_len;
uint8_t nexthdr;
int err;
+ *key_lenp = SW_FLOW_KEY_OFFSET(ipv6.addr);
+
err = check_header(skb, nh_ofs + sizeof(*nh));
if (unlikely(err))
return err;
nexthdr = nh->nexthdr;
payload_ofs = (u8 *)(nh + 1) - skb->data;
- ipv6_addr_copy(&key->ipv6_src, &nh->saddr);
- ipv6_addr_copy(&key->ipv6_dst, &nh->daddr);
- key->nw_tos = ipv6_get_dsfield(nh) & ~INET_ECN_MASK;
- key->nw_proto = NEXTHDR_NONE;
+ key->ip.nw_proto = NEXTHDR_NONE;
+ key->ip.nw_tos = ipv6_get_dsfield(nh) & ~INET_ECN_MASK;
+ ipv6_addr_copy(&key->ipv6.addr.src, &nh->saddr);
+ ipv6_addr_copy(&key->ipv6.addr.dst, &nh->daddr);
payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr);
if (unlikely(payload_ofs < 0))
nh_len = payload_ofs - nh_ofs;
skb_set_transport_header(skb, nh_ofs + nh_len);
- key->nw_proto = nexthdr;
+ key->ip.nw_proto = nexthdr;
return nh_len;
}
{
u8 tcp_flags = 0;
- if (flow->key.dl_type == htons(ETH_P_IP) &&
- flow->key.nw_proto == IPPROTO_TCP) {
+ if (flow->key.eth.type == htons(ETH_P_IP) &&
+ flow->key.ip.nw_proto == IPPROTO_TCP) {
u8 *tcp = (u8 *)tcp_hdr(skb);
tcp_flags = *(tcp + TCP_FLAGS_OFFSET) & TCP_FLAG_MASK;
}
return -ENOMEM;
qp = (struct qtag_prefix *) skb->data;
- key->dl_tci = qp->tci | htons(VLAN_TAG_PRESENT);
+ key->eth.tci = qp->tci | htons(VLAN_TAG_PRESENT);
__skb_pull(skb, sizeof(struct qtag_prefix));
return 0;
}
static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
- int nh_len)
+ int *key_lenp, int nh_len)
{
struct icmp6hdr *icmp = icmp6_hdr(skb);
+ int error = 0;
+ int key_len;
/* The ICMPv6 type and code fields use the 16-bit transport port
* fields, so we need to store them in 16-bit network byte order.
*/
- key->tp_src = htons(icmp->icmp6_type);
- key->tp_dst = htons(icmp->icmp6_code);
+ key->ipv6.tp.src = htons(icmp->icmp6_type);
+ key->ipv6.tp.dst = htons(icmp->icmp6_code);
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
if (icmp->icmp6_code == 0 &&
(icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION ||
struct nd_msg *nd;
int offset;
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.nd);
+
/* In order to process neighbor discovery options, we need the
* entire packet.
*/
if (unlikely(icmp_len < sizeof(*nd)))
- return 0;
- if (unlikely(skb_linearize(skb)))
- return -ENOMEM;
+ goto out;
+ if (unlikely(skb_linearize(skb))) {
+ error = -ENOMEM;
+ goto out;
+ }
nd = (struct nd_msg *)skb_transport_header(skb);
- ipv6_addr_copy(&key->nd_target, &nd->target);
+ ipv6_addr_copy(&key->ipv6.nd.target, &nd->target);
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.nd);
icmp_len -= sizeof(*nd);
offset = 0;
*/
if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LL_ADDR
&& opt_len == 8) {
- if (unlikely(!is_zero_ether_addr(key->arp_sha)))
+ if (unlikely(!is_zero_ether_addr(key->ipv6.nd.sll)))
goto invalid;
- memcpy(key->arp_sha,
+ memcpy(key->ipv6.nd.sll,
&nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
} else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR
&& opt_len == 8) {
- if (unlikely(!is_zero_ether_addr(key->arp_tha)))
+ if (unlikely(!is_zero_ether_addr(key->ipv6.nd.tll)))
goto invalid;
- memcpy(key->arp_tha,
+ memcpy(key->ipv6.nd.tll,
&nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
}
}
}
- return 0;
+ goto out;
invalid:
- memset(&key->nd_target, 0, sizeof(key->nd_target));
- memset(key->arp_sha, 0, sizeof(key->arp_sha));
- memset(key->arp_tha, 0, sizeof(key->arp_tha));
+ memset(&key->ipv6.nd.target, 0, sizeof(key->ipv6.nd.target));
+ memset(key->ipv6.nd.sll, 0, sizeof(key->ipv6.nd.sll));
+ memset(key->ipv6.nd.tll, 0, sizeof(key->ipv6.nd.tll));
- return 0;
+out:
+ *key_lenp = key_len;
+ return error;
}
/**
* Ethernet header
* @in_port: port number on which @skb was received.
* @key: output flow key
+ * @key_lenp: length of output flow key
* @is_frag: set to 1 if @skb contains an IPv4 fragment, or to 0 if @skb does
* not contain an IPv4 packet or if it is not a fragment.
*
* For other key->dl_type values it is left untouched.
*/
int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
- bool *is_frag)
+ int *key_lenp, bool *is_frag)
{
+ int error = 0;
+ int key_len = SW_FLOW_KEY_OFFSET(eth);
struct ethhdr *eth;
memset(key, 0, sizeof(*key));
- key->tun_id = OVS_CB(skb)->tun_id;
- key->in_port = in_port;
+ key->eth.tun_id = OVS_CB(skb)->tun_id;
+ key->eth.in_port = in_port;
*is_frag = false;
skb_reset_mac_header(skb);
* header in the linear data area.
*/
eth = eth_hdr(skb);
- memcpy(key->dl_src, eth->h_source, ETH_ALEN);
- memcpy(key->dl_dst, eth->h_dest, ETH_ALEN);
+ memcpy(key->eth.src, eth->h_source, ETH_ALEN);
+ memcpy(key->eth.dst, eth->h_dest, ETH_ALEN);
+
__skb_pull(skb, 2 * ETH_ALEN);
if (vlan_tx_tag_present(skb))
- key->dl_tci = htons(vlan_get_tci(skb));
+ key->eth.tci = htons(vlan_get_tci(skb));
else if (eth->h_proto == htons(ETH_P_8021Q))
if (unlikely(parse_vlan(skb, key)))
return -ENOMEM;
- key->dl_type = parse_ethertype(skb);
- if (unlikely(key->dl_type == htons(0)))
+ key->eth.type = parse_ethertype(skb);
+ if (unlikely(key->eth.type == htons(0)))
return -ENOMEM;
skb_reset_network_header(skb);
__skb_push(skb, skb->data - skb_mac_header(skb));
/* Network layer. */
- if (key->dl_type == htons(ETH_P_IP)) {
+ if (key->eth.type == htons(ETH_P_IP)) {
struct iphdr *nh;
- int error;
+
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.addr);
error = check_iphdr(skb);
if (unlikely(error)) {
if (error == -EINVAL) {
skb->transport_header = skb->network_header;
- return 0;
+ error = 0;
}
- return error;
+ goto out;
}
nh = ip_hdr(skb);
- key->ipv4_src = nh->saddr;
- key->ipv4_dst = nh->daddr;
- key->nw_tos = nh->tos & ~INET_ECN_MASK;
- key->nw_proto = nh->protocol;
+ key->ipv4.addr.src = nh->saddr;
+ key->ipv4.addr.dst = nh->daddr;
+ key->ip.nw_tos = nh->tos & ~INET_ECN_MASK;
+ key->ip.nw_proto = nh->protocol;
/* Transport layer. */
if (!(nh->frag_off & htons(IP_MF | IP_OFFSET)) &&
!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP)) {
- if (key->nw_proto == IPPROTO_TCP) {
+ if (key->ip.nw_proto == IPPROTO_TCP) {
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
if (tcphdr_ok(skb)) {
struct tcphdr *tcp = tcp_hdr(skb);
- key->tp_src = tcp->source;
- key->tp_dst = tcp->dest;
+ key->ipv4.tp.src = tcp->source;
+ key->ipv4.tp.dst = tcp->dest;
}
- } else if (key->nw_proto == IPPROTO_UDP) {
+ } else if (key->ip.nw_proto == IPPROTO_UDP) {
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
if (udphdr_ok(skb)) {
struct udphdr *udp = udp_hdr(skb);
- key->tp_src = udp->source;
- key->tp_dst = udp->dest;
+ key->ipv4.tp.src = udp->source;
+ key->ipv4.tp.dst = udp->dest;
}
- } else if (key->nw_proto == IPPROTO_ICMP) {
+ } else if (key->ip.nw_proto == IPPROTO_ICMP) {
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
if (icmphdr_ok(skb)) {
struct icmphdr *icmp = icmp_hdr(skb);
/* The ICMP type and code fields use the 16-bit
* transport port fields, so we need to store them
* in 16-bit network byte order. */
- key->tp_src = htons(icmp->type);
- key->tp_dst = htons(icmp->code);
+ key->ipv4.tp.src = htons(icmp->type);
+ key->ipv4.tp.dst = htons(icmp->code);
}
}
} else
*is_frag = true;
- } else if (key->dl_type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
+ } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
struct arp_eth_header *arp;
arp = (struct arp_eth_header *)skb_network_header(skb);
/* We only match on the lower 8 bits of the opcode. */
if (ntohs(arp->ar_op) <= 0xff)
- key->nw_proto = ntohs(arp->ar_op);
-
- if (key->nw_proto == ARPOP_REQUEST
- || key->nw_proto == ARPOP_REPLY) {
- memcpy(&key->ipv4_src, arp->ar_sip, sizeof(key->ipv4_src));
- memcpy(&key->ipv4_dst, arp->ar_tip, sizeof(key->ipv4_dst));
- memcpy(key->arp_sha, arp->ar_sha, ETH_ALEN);
- memcpy(key->arp_tha, arp->ar_tha, ETH_ALEN);
+ key->ip.nw_proto = ntohs(arp->ar_op);
+
+ if (key->ip.nw_proto == ARPOP_REQUEST
+ || key->ip.nw_proto == ARPOP_REPLY) {
+ memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
+ memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
+ memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
+ memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
}
}
- } else if (key->dl_type == htons(ETH_P_IPV6)) {
+ } else if (key->eth.type == htons(ETH_P_IPV6)) {
int nh_len; /* IPv6 Header + Extensions */
- nh_len = parse_ipv6hdr(skb, key);
+ nh_len = parse_ipv6hdr(skb, key, &key_len);
if (unlikely(nh_len < 0)) {
- if (nh_len == -EINVAL) {
+ if (nh_len == -EINVAL)
skb->transport_header = skb->network_header;
- return 0;
- }
- return nh_len;
+ else
+ error = nh_len;
+ goto out;
}
/* Transport layer. */
- if (key->nw_proto == NEXTHDR_TCP) {
+ if (key->ip.nw_proto == NEXTHDR_TCP) {
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
if (tcphdr_ok(skb)) {
struct tcphdr *tcp = tcp_hdr(skb);
- key->tp_src = tcp->source;
- key->tp_dst = tcp->dest;
+ key->ipv6.tp.src = tcp->source;
+ key->ipv6.tp.dst = tcp->dest;
}
- } else if (key->nw_proto == NEXTHDR_UDP) {
+ } else if (key->ip.nw_proto == NEXTHDR_UDP) {
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
if (udphdr_ok(skb)) {
struct udphdr *udp = udp_hdr(skb);
- key->tp_src = udp->source;
- key->tp_dst = udp->dest;
+ key->ipv6.tp.src = udp->source;
+ key->ipv6.tp.dst = udp->dest;
}
- } else if (key->nw_proto == NEXTHDR_ICMP) {
+ } else if (key->ip.nw_proto == NEXTHDR_ICMP) {
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
if (icmp6hdr_ok(skb)) {
- int error = parse_icmpv6(skb, key, nh_len);
+ error = parse_icmpv6(skb, key, &key_len, nh_len);
if (error < 0)
- return error;
+ goto out;
}
}
}
- return 0;
+
+out:
+ *key_lenp = key_len;
+ return error;
}
-u32 flow_hash(const struct sw_flow_key *key)
+u32 flow_hash(const struct sw_flow_key *key, int key_len)
{
- return jhash2((u32*)key, sizeof(*key) / sizeof(u32), hash_seed);
+ return jhash2((u32*)key, DIV_ROUND_UP(key_len, sizeof(u32)), hash_seed);
}
-int flow_cmp(const struct tbl_node *node, void *key2_)
+int flow_cmp(const struct tbl_node *node, void *key2_, int len)
{
const struct sw_flow_key *key1 = &flow_cast(node)->key;
const struct sw_flow_key *key2 = key2_;
- return !memcmp(key1, key2, sizeof(struct sw_flow_key));
+ return !memcmp(key1, key2, len);
}
/**
* flow_from_nlattrs - parses Netlink attributes into a flow key.
* @swkey: receives the extracted flow key.
- * @key: Netlink attribute holding nested %ODP_KEY_ATTR_* Netlink attribute
+ * @key_lenp: number of bytes used in @swkey.
+ * @attr: Netlink attribute holding nested %ODP_KEY_ATTR_* Netlink attribute
* sequence.
*
* This state machine accepts the following forms, with [] for optional
* [tun_id] in_port ethernet [8021q] [ethertype \
* [IPv4 [TCP|UDP|ICMP] | IPv6 [TCP|UDP|ICMPv6 [ND]] | ARP]]
*/
-int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
+int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
+ const struct nlattr *attr)
{
+ int error = 0;
const struct nlattr *nla;
u16 prev_type;
int rem;
+ int key_len;
memset(swkey, 0, sizeof(*swkey));
- swkey->dl_type = htons(ETH_P_802_2);
+ swkey->eth.type = htons(ETH_P_802_2);
+ key_len = SW_FLOW_KEY_OFFSET(eth);
prev_type = ODP_KEY_ATTR_UNSPEC;
nla_for_each_nested(nla, attr, rem) {
int type = nla_type(nla);
if (type > ODP_KEY_ATTR_MAX || nla_len(nla) != key_lens[type])
- return -EINVAL;
+ goto invalid;
#define TRANSITION(PREV_TYPE, TYPE) (((PREV_TYPE) << 16) | (TYPE))
switch (TRANSITION(prev_type, type)) {
case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_TUN_ID):
- swkey->tun_id = nla_get_be64(nla);
+ swkey->eth.tun_id = nla_get_be64(nla);
break;
case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_IN_PORT):
case TRANSITION(ODP_KEY_ATTR_TUN_ID, ODP_KEY_ATTR_IN_PORT):
if (nla_get_u32(nla) >= DP_MAX_PORTS)
- return -EINVAL;
- swkey->in_port = nla_get_u32(nla);
+ goto invalid;
+ swkey->eth.in_port = nla_get_u32(nla);
break;
case TRANSITION(ODP_KEY_ATTR_IN_PORT, ODP_KEY_ATTR_ETHERNET):
eth_key = nla_data(nla);
- memcpy(swkey->dl_src, eth_key->eth_src, ETH_ALEN);
- memcpy(swkey->dl_dst, eth_key->eth_dst, ETH_ALEN);
+ memcpy(swkey->eth.src, eth_key->eth_src, ETH_ALEN);
+ memcpy(swkey->eth.dst, eth_key->eth_dst, ETH_ALEN);
break;
case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_8021Q):
q_key = nla_data(nla);
/* Only standard 0x8100 VLANs currently supported. */
if (q_key->q_tpid != htons(ETH_P_8021Q))
- return -EINVAL;
+ goto invalid;
if (q_key->q_tci & htons(VLAN_TAG_PRESENT))
- return -EINVAL;
- swkey->dl_tci = q_key->q_tci | htons(VLAN_TAG_PRESENT);
+ goto invalid;
+ swkey->eth.tci = q_key->q_tci | htons(VLAN_TAG_PRESENT);
break;
case TRANSITION(ODP_KEY_ATTR_8021Q, ODP_KEY_ATTR_ETHERTYPE):
case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_ETHERTYPE):
- swkey->dl_type = nla_get_be16(nla);
- if (ntohs(swkey->dl_type) < 1536)
- return -EINVAL;
+ swkey->eth.type = nla_get_be16(nla);
+ if (ntohs(swkey->eth.type) < 1536)
+ goto invalid;
break;
case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_IPV4):
- if (swkey->dl_type != htons(ETH_P_IP))
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.addr);
+ if (swkey->eth.type != htons(ETH_P_IP))
+ goto invalid;
ipv4_key = nla_data(nla);
- swkey->ipv4_src = ipv4_key->ipv4_src;
- swkey->ipv4_dst = ipv4_key->ipv4_dst;
- swkey->nw_proto = ipv4_key->ipv4_proto;
- swkey->nw_tos = ipv4_key->ipv4_tos;
- if (swkey->nw_tos & INET_ECN_MASK)
- return -EINVAL;
+ swkey->ip.nw_proto = ipv4_key->ipv4_proto;
+ swkey->ip.nw_tos = ipv4_key->ipv4_tos;
+ swkey->ipv4.addr.src = ipv4_key->ipv4_src;
+ swkey->ipv4.addr.dst = ipv4_key->ipv4_dst;
+ if (swkey->ip.nw_tos & INET_ECN_MASK)
+ goto invalid;
break;
case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_IPV6):
- if (swkey->dl_type != htons(ETH_P_IPV6))
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.addr);
+ if (swkey->eth.type != htons(ETH_P_IPV6))
+ goto invalid;
ipv6_key = nla_data(nla);
- memcpy(&swkey->ipv6_src, ipv6_key->ipv6_src,
- sizeof(swkey->ipv6_src));
- memcpy(&swkey->ipv6_dst, ipv6_key->ipv6_dst,
- sizeof(swkey->ipv6_dst));
- swkey->nw_proto = ipv6_key->ipv6_proto;
- swkey->nw_tos = ipv6_key->ipv6_tos;
- if (swkey->nw_tos & INET_ECN_MASK)
- return -EINVAL;
+ swkey->ip.nw_proto = ipv6_key->ipv6_proto;
+ swkey->ip.nw_tos = ipv6_key->ipv6_tos;
+ memcpy(&swkey->ipv6.addr.src, ipv6_key->ipv6_src,
+ sizeof(swkey->ipv6.addr.src));
+ memcpy(&swkey->ipv6.addr.dst, ipv6_key->ipv6_dst,
+ sizeof(swkey->ipv6.addr.dst));
+ if (swkey->ip.nw_tos & INET_ECN_MASK)
+ goto invalid;
break;
case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_TCP):
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
+ if (swkey->ip.nw_proto != IPPROTO_TCP)
+ goto invalid;
+ tcp_key = nla_data(nla);
+ swkey->ipv4.tp.src = tcp_key->tcp_src;
+ swkey->ipv4.tp.dst = tcp_key->tcp_dst;
+ break;
+
case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_TCP):
- if (swkey->nw_proto != IPPROTO_TCP)
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
+ if (swkey->ip.nw_proto != IPPROTO_TCP)
+ goto invalid;
tcp_key = nla_data(nla);
- swkey->tp_src = tcp_key->tcp_src;
- swkey->tp_dst = tcp_key->tcp_dst;
+ swkey->ipv6.tp.src = tcp_key->tcp_src;
+ swkey->ipv6.tp.dst = tcp_key->tcp_dst;
break;
case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_UDP):
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
+ if (swkey->ip.nw_proto != IPPROTO_UDP)
+ goto invalid;
+ udp_key = nla_data(nla);
+ swkey->ipv4.tp.src = udp_key->udp_src;
+ swkey->ipv4.tp.dst = udp_key->udp_dst;
+ break;
+
case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_UDP):
- if (swkey->nw_proto != IPPROTO_UDP)
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
+ if (swkey->ip.nw_proto != IPPROTO_UDP)
+ goto invalid;
udp_key = nla_data(nla);
- swkey->tp_src = udp_key->udp_src;
- swkey->tp_dst = udp_key->udp_dst;
+ swkey->ipv6.tp.src = udp_key->udp_src;
+ swkey->ipv6.tp.dst = udp_key->udp_dst;
break;
case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_ICMP):
- if (swkey->nw_proto != IPPROTO_ICMP)
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.tp);
+ if (swkey->ip.nw_proto != IPPROTO_ICMP)
+ goto invalid;
icmp_key = nla_data(nla);
- swkey->tp_src = htons(icmp_key->icmp_type);
- swkey->tp_dst = htons(icmp_key->icmp_code);
+ swkey->ipv4.tp.src = htons(icmp_key->icmp_type);
+ swkey->ipv4.tp.dst = htons(icmp_key->icmp_code);
break;
case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_ICMPV6):
- if (swkey->nw_proto != IPPROTO_ICMPV6)
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.tp);
+ if (swkey->ip.nw_proto != IPPROTO_ICMPV6)
+ goto invalid;
icmpv6_key = nla_data(nla);
- swkey->tp_src = htons(icmpv6_key->icmpv6_type);
- swkey->tp_dst = htons(icmpv6_key->icmpv6_code);
+ swkey->ipv6.tp.src = htons(icmpv6_key->icmpv6_type);
+ swkey->ipv6.tp.dst = htons(icmpv6_key->icmpv6_code);
break;
case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_ARP):
- if (swkey->dl_type != htons(ETH_P_ARP))
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
+ if (swkey->eth.type != htons(ETH_P_ARP))
+ goto invalid;
arp_key = nla_data(nla);
- swkey->ipv4_src = arp_key->arp_sip;
- swkey->ipv4_dst = arp_key->arp_tip;
+ swkey->ipv4.addr.src = arp_key->arp_sip;
+ swkey->ipv4.addr.dst = arp_key->arp_tip;
if (arp_key->arp_op & htons(0xff00))
- return -EINVAL;
- swkey->nw_proto = ntohs(arp_key->arp_op);
- memcpy(swkey->arp_sha, arp_key->arp_sha, ETH_ALEN);
- memcpy(swkey->arp_tha, arp_key->arp_tha, ETH_ALEN);
+ goto invalid;
+ swkey->ip.nw_proto = ntohs(arp_key->arp_op);
+ memcpy(swkey->ipv4.arp.sha, arp_key->arp_sha, ETH_ALEN);
+ memcpy(swkey->ipv4.arp.tha, arp_key->arp_tha, ETH_ALEN);
break;
case TRANSITION(ODP_KEY_ATTR_ICMPV6, ODP_KEY_ATTR_ND):
- if (swkey->tp_src != htons(NDISC_NEIGHBOUR_SOLICITATION)
- && swkey->tp_src != htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
- return -EINVAL;
+ key_len = SW_FLOW_KEY_OFFSET(ipv6.nd);
+ if (swkey->ipv6.tp.src != htons(NDISC_NEIGHBOUR_SOLICITATION)
+ && swkey->ipv6.tp.src != htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
+ goto invalid;
nd_key = nla_data(nla);
- memcpy(&swkey->nd_target, nd_key->nd_target,
- sizeof(swkey->nd_target));
- memcpy(swkey->arp_sha, nd_key->nd_sll, ETH_ALEN);
- memcpy(swkey->arp_tha, nd_key->nd_tll, ETH_ALEN);
+ memcpy(&swkey->ipv6.nd.target, nd_key->nd_target,
+ sizeof(swkey->ipv6.nd.target));
+ memcpy(swkey->ipv6.nd.sll, nd_key->nd_sll, ETH_ALEN);
+ memcpy(swkey->ipv6.nd.tll, nd_key->nd_tll, ETH_ALEN);
break;
default:
- return -EINVAL;
+ goto invalid;
}
prev_type = type;
}
if (rem)
- return -EINVAL;
+ goto invalid;
switch (prev_type) {
case ODP_KEY_ATTR_UNSPEC:
- return -EINVAL;
+ goto invalid;
case ODP_KEY_ATTR_TUN_ID:
case ODP_KEY_ATTR_IN_PORT:
- return -EINVAL;
+ goto invalid;
case ODP_KEY_ATTR_ETHERNET:
case ODP_KEY_ATTR_8021Q:
- return 0;
+ goto ok;
case ODP_KEY_ATTR_ETHERTYPE:
- if (swkey->dl_type == htons(ETH_P_IP) ||
- swkey->dl_type == htons(ETH_P_ARP))
- return -EINVAL;
- return 0;
+ if (swkey->eth.type == htons(ETH_P_IP) ||
+ swkey->eth.type == htons(ETH_P_ARP))
+ goto invalid;
+ goto ok;
case ODP_KEY_ATTR_IPV4:
- if (swkey->nw_proto == IPPROTO_TCP ||
- swkey->nw_proto == IPPROTO_UDP ||
- swkey->nw_proto == IPPROTO_ICMP)
- return -EINVAL;
- return 0;
+ if (swkey->ip.nw_proto == IPPROTO_TCP ||
+ swkey->ip.nw_proto == IPPROTO_UDP ||
+ swkey->ip.nw_proto == IPPROTO_ICMP)
+ goto invalid;
+ goto ok;
case ODP_KEY_ATTR_IPV6:
- if (swkey->nw_proto == IPPROTO_TCP ||
- swkey->nw_proto == IPPROTO_UDP ||
- swkey->nw_proto == IPPROTO_ICMPV6)
- return -EINVAL;
- return 0;
+ if (swkey->ip.nw_proto == IPPROTO_TCP ||
+ swkey->ip.nw_proto == IPPROTO_UDP ||
+ swkey->ip.nw_proto == IPPROTO_ICMPV6)
+ goto invalid;
+ goto ok;
case ODP_KEY_ATTR_ICMPV6:
- if (swkey->tp_src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
- swkey->tp_src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
- return -EINVAL;
- return 0;
+ if (swkey->ipv6.tp.src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
+ swkey->ipv6.tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
+ goto invalid;
+ goto ok;
case ODP_KEY_ATTR_TCP:
case ODP_KEY_ATTR_UDP:
case ODP_KEY_ATTR_ICMP:
case ODP_KEY_ATTR_ARP:
case ODP_KEY_ATTR_ND:
- return 0;
+ goto ok;
+
+ default:
+ WARN_ON_ONCE(1);
}
- WARN_ON_ONCE(1);
- return -EINVAL;
+invalid:
+ error = -EINVAL;
+
+ok:
+ WARN_ON_ONCE(!key_len && !error);
+ *key_lenp = key_len;
+ return error;
}
int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
* types are added. */
BUILD_BUG_ON(__ODP_KEY_ATTR_MAX != 14);
- if (swkey->tun_id != cpu_to_be64(0))
- NLA_PUT_BE64(skb, ODP_KEY_ATTR_TUN_ID, swkey->tun_id);
+ if (swkey->eth.tun_id != cpu_to_be64(0))
+ NLA_PUT_BE64(skb, ODP_KEY_ATTR_TUN_ID, swkey->eth.tun_id);
- NLA_PUT_U32(skb, ODP_KEY_ATTR_IN_PORT, swkey->in_port);
+ NLA_PUT_U32(skb, ODP_KEY_ATTR_IN_PORT, swkey->eth.in_port);
nla = nla_reserve(skb, ODP_KEY_ATTR_ETHERNET, sizeof(*eth_key));
if (!nla)
goto nla_put_failure;
eth_key = nla_data(nla);
- memcpy(eth_key->eth_src, swkey->dl_src, ETH_ALEN);
- memcpy(eth_key->eth_dst, swkey->dl_dst, ETH_ALEN);
+ memcpy(eth_key->eth_src, swkey->eth.src, ETH_ALEN);
+ memcpy(eth_key->eth_dst, swkey->eth.dst, ETH_ALEN);
- if (swkey->dl_tci != htons(0)) {
+ if (swkey->eth.tci != htons(0)) {
struct odp_key_8021q q_key;
q_key.q_tpid = htons(ETH_P_8021Q);
- q_key.q_tci = swkey->dl_tci & ~htons(VLAN_TAG_PRESENT);
+ q_key.q_tci = swkey->eth.tci & ~htons(VLAN_TAG_PRESENT);
NLA_PUT(skb, ODP_KEY_ATTR_8021Q, sizeof(q_key), &q_key);
}
- if (swkey->dl_type == htons(ETH_P_802_2))
+ if (swkey->eth.type == htons(ETH_P_802_2))
return 0;
- NLA_PUT_BE16(skb, ODP_KEY_ATTR_ETHERTYPE, swkey->dl_type);
+ NLA_PUT_BE16(skb, ODP_KEY_ATTR_ETHERTYPE, swkey->eth.type);
- if (swkey->dl_type == htons(ETH_P_IP)) {
+ if (swkey->eth.type == htons(ETH_P_IP)) {
struct odp_key_ipv4 *ipv4_key;
nla = nla_reserve(skb, ODP_KEY_ATTR_IPV4, sizeof(*ipv4_key));
goto nla_put_failure;
ipv4_key = nla_data(nla);
memset(ipv4_key, 0, sizeof(struct odp_key_ipv4));
- ipv4_key->ipv4_src = swkey->ipv4_src;
- ipv4_key->ipv4_dst = swkey->ipv4_dst;
- ipv4_key->ipv4_proto = swkey->nw_proto;
- ipv4_key->ipv4_tos = swkey->nw_tos;
- } else if (swkey->dl_type == htons(ETH_P_IPV6)) {
+ ipv4_key->ipv4_src = swkey->ipv4.addr.src;
+ ipv4_key->ipv4_dst = swkey->ipv4.addr.dst;
+ ipv4_key->ipv4_proto = swkey->ip.nw_proto;
+ ipv4_key->ipv4_tos = swkey->ip.nw_tos;
+ } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
struct odp_key_ipv6 *ipv6_key;
nla = nla_reserve(skb, ODP_KEY_ATTR_IPV6, sizeof(*ipv6_key));
goto nla_put_failure;
ipv6_key = nla_data(nla);
memset(ipv6_key, 0, sizeof(struct odp_key_ipv6));
- memcpy(ipv6_key->ipv6_src, &swkey->ipv6_src,
+ memcpy(ipv6_key->ipv6_src, &swkey->ipv6.addr.src,
sizeof(ipv6_key->ipv6_src));
- memcpy(ipv6_key->ipv6_dst, &swkey->ipv6_dst,
+ memcpy(ipv6_key->ipv6_dst, &swkey->ipv6.addr.dst,
sizeof(ipv6_key->ipv6_dst));
- ipv6_key->ipv6_proto = swkey->nw_proto;
- ipv6_key->ipv6_tos = swkey->nw_tos;
- } else if (swkey->dl_type == htons(ETH_P_ARP)) {
+ ipv6_key->ipv6_proto = swkey->ip.nw_proto;
+ ipv6_key->ipv6_tos = swkey->ip.nw_tos;
+ } else if (swkey->eth.type == htons(ETH_P_ARP)) {
struct odp_key_arp *arp_key;
nla = nla_reserve(skb, ODP_KEY_ATTR_ARP, sizeof(*arp_key));
goto nla_put_failure;
arp_key = nla_data(nla);
memset(arp_key, 0, sizeof(struct odp_key_arp));
- arp_key->arp_sip = swkey->ipv4_src;
- arp_key->arp_tip = swkey->ipv4_dst;
- arp_key->arp_op = htons(swkey->nw_proto);
- memcpy(arp_key->arp_sha, swkey->arp_sha, ETH_ALEN);
- memcpy(arp_key->arp_tha, swkey->arp_tha, ETH_ALEN);
+ arp_key->arp_sip = swkey->ipv4.addr.src;
+ arp_key->arp_tip = swkey->ipv4.addr.dst;
+ arp_key->arp_op = htons(swkey->ip.nw_proto);
+ memcpy(arp_key->arp_sha, swkey->ipv4.arp.sha, ETH_ALEN);
+ memcpy(arp_key->arp_tha, swkey->ipv4.arp.tha, ETH_ALEN);
}
- if (swkey->dl_type == htons(ETH_P_IP) ||
- swkey->dl_type == htons(ETH_P_IPV6)) {
+ if (swkey->eth.type == htons(ETH_P_IP) ||
+ swkey->eth.type == htons(ETH_P_IPV6)) {
- if (swkey->nw_proto == IPPROTO_TCP) {
+ if (swkey->ip.nw_proto == IPPROTO_TCP) {
struct odp_key_tcp *tcp_key;
nla = nla_reserve(skb, ODP_KEY_ATTR_TCP, sizeof(*tcp_key));
if (!nla)
goto nla_put_failure;
tcp_key = nla_data(nla);
- tcp_key->tcp_src = swkey->tp_src;
- tcp_key->tcp_dst = swkey->tp_dst;
- } else if (swkey->nw_proto == IPPROTO_UDP) {
+ if (swkey->eth.type == htons(ETH_P_IP)) {
+ tcp_key->tcp_src = swkey->ipv4.tp.src;
+ tcp_key->tcp_dst = swkey->ipv4.tp.dst;
+ } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
+ tcp_key->tcp_src = swkey->ipv6.tp.src;
+ tcp_key->tcp_dst = swkey->ipv6.tp.dst;
+ }
+ } else if (swkey->ip.nw_proto == IPPROTO_UDP) {
struct odp_key_udp *udp_key;
nla = nla_reserve(skb, ODP_KEY_ATTR_UDP, sizeof(*udp_key));
if (!nla)
goto nla_put_failure;
udp_key = nla_data(nla);
- udp_key->udp_src = swkey->tp_src;
- udp_key->udp_dst = swkey->tp_dst;
- } else if (swkey->dl_type == htons(ETH_P_IP) &&
- swkey->nw_proto == IPPROTO_ICMP) {
+ if (swkey->eth.type == htons(ETH_P_IP)) {
+ udp_key->udp_src = swkey->ipv4.tp.src;
+ udp_key->udp_dst = swkey->ipv4.tp.dst;
+ } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
+ udp_key->udp_src = swkey->ipv6.tp.src;
+ udp_key->udp_dst = swkey->ipv6.tp.dst;
+ }
+ } else if (swkey->eth.type == htons(ETH_P_IP) &&
+ swkey->ip.nw_proto == IPPROTO_ICMP) {
struct odp_key_icmp *icmp_key;
nla = nla_reserve(skb, ODP_KEY_ATTR_ICMP, sizeof(*icmp_key));
if (!nla)
goto nla_put_failure;
icmp_key = nla_data(nla);
- icmp_key->icmp_type = ntohs(swkey->tp_src);
- icmp_key->icmp_code = ntohs(swkey->tp_dst);
- } else if (swkey->dl_type == htons(ETH_P_IPV6) &&
- swkey->nw_proto == IPPROTO_ICMPV6) {
+ icmp_key->icmp_type = ntohs(swkey->ipv4.tp.src);
+ icmp_key->icmp_code = ntohs(swkey->ipv4.tp.dst);
+ } else if (swkey->eth.type == htons(ETH_P_IPV6) &&
+ swkey->ip.nw_proto == IPPROTO_ICMPV6) {
struct odp_key_icmpv6 *icmpv6_key;
nla = nla_reserve(skb, ODP_KEY_ATTR_ICMPV6,
if (!nla)
goto nla_put_failure;
icmpv6_key = nla_data(nla);
- icmpv6_key->icmpv6_type = ntohs(swkey->tp_src);
- icmpv6_key->icmpv6_code = ntohs(swkey->tp_dst);
+ icmpv6_key->icmpv6_type = ntohs(swkey->ipv6.tp.src);
+ icmpv6_key->icmpv6_code = ntohs(swkey->ipv6.tp.dst);
if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION ||
icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
if (!nla)
goto nla_put_failure;
nd_key = nla_data(nla);
- memcpy(nd_key->nd_target, &swkey->nd_target,
+ memcpy(nd_key->nd_target, &swkey->ipv6.nd.target,
sizeof(nd_key->nd_target));
- memcpy(nd_key->nd_sll, swkey->arp_sha, ETH_ALEN);
- memcpy(nd_key->nd_tll, swkey->arp_tha, ETH_ALEN);
+ memcpy(nd_key->nd_sll, swkey->ipv6.nd.sll, ETH_ALEN);
+ memcpy(nd_key->nd_tll, swkey->ipv6.nd.tll, ETH_ALEN);
}
}
}
};
struct sw_flow_key {
- __be64 tun_id; /* Encapsulating tunnel ID. */
+ struct {
+ __be64 tun_id; /* Encapsulating tunnel ID. */
+ u16 in_port; /* Input switch port. */
+ u8 src[ETH_ALEN]; /* Ethernet source address. */
+ u8 dst[ETH_ALEN]; /* Ethernet destination address. */
+ __be16 tci; /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
+ __be16 type; /* Ethernet frame type. */
+ } eth;
+ struct {
+ u8 nw_proto; /* IP protocol or lower 8 bits of ARP opcode. */
+ u8 nw_tos; /* IP ToS (DSCP field, 6 bits). */
+ } ip;
union {
struct {
- __be32 ipv4_src; /* IPv4 source address. */
- __be32 ipv4_dst; /* IPv4 destination address. */
- };
+ struct {
+ __be32 src; /* IP source address. */
+ __be32 dst; /* IP destination address. */
+ } addr;
+ union {
+ struct {
+ __be16 src; /* TCP/UDP source port. */
+ __be16 dst; /* TCP/UDP destination port. */
+ } tp;
+ struct {
+ u8 sha[ETH_ALEN]; /* ARP source hardware address. */
+ u8 tha[ETH_ALEN]; /* ARP target hardware address. */
+ } arp;
+ };
+ } ipv4;
struct {
- struct in6_addr ipv6_src; /* IPv6 source address. */
- struct in6_addr ipv6_dst; /* IPv6 source address. */
- };
+ struct {
+ struct in6_addr src; /* IPv6 source address. */
+ struct in6_addr dst; /* IPv6 destination address. */
+ } addr;
+ struct {
+ __be16 src; /* TCP/UDP source port. */
+ __be16 dst; /* TCP/UDP destination port. */
+ } tp;
+ struct {
+ struct in6_addr target; /* ND target address. */
+ u8 sll[ETH_ALEN]; /* ND source link layer address. */
+ u8 tll[ETH_ALEN]; /* ND target link layer address. */
+ } nd;
+ } ipv6;
};
- struct in6_addr nd_target; /* IPv6 ND target address. */
- u16 in_port; /* Input switch port. */
- __be16 dl_tci; /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
- __be16 dl_type; /* Ethernet frame type. */
- __be16 tp_src; /* TCP/UDP source port. */
- __be16 tp_dst; /* TCP/UDP destination port. */
- u8 dl_src[ETH_ALEN]; /* Ethernet source address. */
- u8 dl_dst[ETH_ALEN]; /* Ethernet destination address. */
- u8 nw_proto; /* IP protocol or lower 8 bits of ARP opcode. */
- u8 nw_tos; /* IP ToS (DSCP field, 6 bits). */
- u8 arp_sha[ETH_ALEN]; /* ARP/ND source hardware address. */
- u8 arp_tha[ETH_ALEN]; /* ARP/ND target hardware address. */
};
struct sw_flow {
void flow_hold(struct sw_flow *);
void flow_put(struct sw_flow *);
-int flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *, bool *is_frag);
+int flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *,
+ int *key_lenp, bool *is_frag);
void flow_used(struct sw_flow *, struct sk_buff *);
u64 flow_used_time(unsigned long flow_jiffies);
-u32 flow_hash(const struct sw_flow_key *);
-int flow_cmp(const struct tbl_node *, void *target);
+u32 flow_hash(const struct sw_flow_key *, int key_lenp);
+int flow_cmp(const struct tbl_node *, void *target, int len);
/* Upper bound on the length of a nlattr-formatted flow key. The longest
* nlattr-formatted flow key would be:
#define FLOW_BUFSIZE 132
int flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
-int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *);
+int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
+ const struct nlattr *);
static inline struct sw_flow *flow_cast(const struct tbl_node *node)
{
return &table->buckets[l1][l2];
}
-static int search_bucket(const struct tbl_bucket *bucket, void *target, u32 hash,
- int (*cmp)(const struct tbl_node *, void *))
+static int search_bucket(const struct tbl_bucket *bucket, void *target, int len, u32 hash,
+ int (*cmp)(const struct tbl_node *, void *, int len))
{
int i;
for (i = 0; i < bucket->n_objs; i++) {
struct tbl_node *obj = bucket->objs[i];
- if (obj->hash == hash && likely(cmp(obj, target)))
+ if (obj->hash == hash && likely(cmp(obj, target, len)))
return i;
}
* @table: hash table to search
* @target: identifier for the object that is being searched for, will be
* provided as an argument to @cmp when making comparisions
+ * @len: length of @target in bytes, will be provided as an argument to @cmp
+ * when making comparisons
* @hash: hash of @target
* @cmp: comparision function to match objects with the given hash, returns
* nonzero if the objects match, zero otherwise
* Searches @table for an object identified by @target. Returns the tbl_node
* contained in the object if successful, otherwise %NULL.
*/
-struct tbl_node *tbl_lookup(struct tbl *table, void *target, u32 hash,
- int (*cmp)(const struct tbl_node *, void *))
+struct tbl_node *tbl_lookup(struct tbl *table, void *target, int len, u32 hash,
+ int (*cmp)(const struct tbl_node *, void *, int))
{
struct tbl_bucket __rcu **bucketp = find_bucket(table, hash);
struct tbl_bucket *bucket = get_bucket(*bucketp);
if (!bucket)
return NULL;
- index = search_bucket(bucket, target, hash, cmp);
+ index = search_bucket(bucket, target, len, hash, cmp);
if (index < 0)
return NULL;
struct tbl *tbl_create(unsigned int n_buckets);
void tbl_destroy(struct tbl *, void (*destructor)(struct tbl_node *));
-struct tbl_node *tbl_lookup(struct tbl *, void *target, u32 hash,
- int (*cmp)(const struct tbl_node *, void *target));
+struct tbl_node *tbl_lookup(struct tbl *, void *target, int len, u32 hash,
+ int (*cmp)(const struct tbl_node *, void *target, int len));
int tbl_insert(struct tbl *, struct tbl_node *, u32 hash);
int tbl_remove(struct tbl *, struct tbl_node *);
unsigned int tbl_count(struct tbl *);
* Modifies 'target' to store the rcu_dereferenced pointer that was used to do
* the comparision.
*/
-static int port_cmp(const struct tbl_node *node, void *target)
+static int port_cmp(const struct tbl_node *node, void *target, int unused)
{
const struct tnl_vport *tnl_vport = tnl_vport_table_cast(node);
struct port_lookup_key *lookup = target;
lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_MATCH;
if (key_local_remote_ports) {
- tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+ tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+ port_hash(&lookup), port_cmp);
if (tbl_node)
goto found;
}
if (key_remote_ports) {
lookup.saddr = 0;
- tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+ tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+ port_hash(&lookup), port_cmp);
if (tbl_node)
goto found;
lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_EXACT;
if (local_remote_ports) {
- tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+ tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+ port_hash(&lookup), port_cmp);
if (tbl_node)
goto found;
}
if (remote_ports) {
lookup.saddr = 0;
- tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+ tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+ port_hash(&lookup), port_cmp);
if (tbl_node)
goto found;
}
struct sk_buff *skb;
bool is_frag;
int err;
+ int flow_key_len;
dst_vport = internal_dev_get_vport(rt_dst(rt).dev);
if (!dst_vport)
__skb_put(skb, cache->len);
memcpy(skb->data, get_cached_header(cache), cache->len);
- err = flow_extract(skb, dst_vport->port_no, &flow_key, &is_frag);
+ err = flow_extract(skb, dst_vport->port_no, &flow_key,
+ &flow_key_len, &is_frag);
kfree_skb(skb);
if (err || is_frag)
goto done;
flow_node = tbl_lookup(rcu_dereference(dst_vport->dp->table),
- &flow_key, flow_hash(&flow_key),
+ &flow_key, flow_key_len,
+ flow_hash(&flow_key, flow_key_len),
flow_cmp);
if (flow_node) {
struct sw_flow *flow = flow_cast(flow_node);
return 0
if k == '--output':
- if v in ['tar', 'tar.bz2', 'zip']:
+ if v in ['tar', 'tar.bz2', 'tar.gz', 'zip']:
output_type = v
else:
print >>sys.stderr, "Invalid output format '%s'" % v
mode = 'w'
if suffix == 'tar.bz2':
mode = 'w:bz2'
+ elif suffix == 'tar.gz':
+ mode = 'w:gz'
filename = "%s/%s.%s" % (BUG_DIR, subdir, suffix)
if output_fd == -1:
include include/linux/automake.mk
include include/openflow/automake.mk
include include/openvswitch/automake.mk
+include include/sparse/automake.mk
struct ofp_header {
uint8_t version; /* OFP_VERSION. */
uint8_t type; /* One of the OFPT_ constants. */
- uint16_t length; /* Length including this ofp_header. */
- uint32_t xid; /* Transaction id associated with this packet.
+ ovs_be16 length; /* Length including this ofp_header. */
+ ovs_be32 xid; /* Transaction id associated with this packet.
Replies use the same id as was in the request
to facilitate pairing. */
};
/* Switch configuration. */
struct ofp_switch_config {
struct ofp_header header;
- uint16_t flags; /* OFPC_* flags. */
- uint16_t miss_send_len; /* Max bytes of new flow that datapath should
+ ovs_be16 flags; /* OFPC_* flags. */
+ ovs_be16 miss_send_len; /* Max bytes of new flow that datapath should
send to the controller. */
};
OFP_ASSERT(sizeof(struct ofp_switch_config) == 12);
/* Description of a physical port */
struct ofp_phy_port {
- uint16_t port_no;
+ ovs_be16 port_no;
uint8_t hw_addr[OFP_ETH_ALEN];
char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */
- uint32_t config; /* Bitmap of OFPPC_* flags. */
- uint32_t state; /* Bitmap of OFPPS_* flags. */
+ ovs_be32 config; /* Bitmap of OFPPC_* flags. */
+ ovs_be32 state; /* Bitmap of OFPPS_* flags. */
/* Bitmaps of OFPPF_* that describe features. All bits zeroed if
* unsupported or unavailable. */
- uint32_t curr; /* Current features. */
- uint32_t advertised; /* Features being advertised by the port. */
- uint32_t supported; /* Features supported by the port. */
- uint32_t peer; /* Features advertised by peer. */
+ ovs_be32 curr; /* Current features. */
+ ovs_be32 advertised; /* Features being advertised by the port. */
+ ovs_be32 supported; /* Features supported by the port. */
+ ovs_be32 peer; /* Features advertised by peer. */
};
OFP_ASSERT(sizeof(struct ofp_phy_port) == 48);
/* Switch features. */
struct ofp_switch_features {
struct ofp_header header;
- uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for
+ ovs_be64 datapath_id; /* Datapath unique ID. The lower 48-bits are for
a MAC address, while the upper 16-bits are
implementer-defined. */
- uint32_t n_buffers; /* Max packets buffered at once. */
+ ovs_be32 n_buffers; /* Max packets buffered at once. */
uint8_t n_tables; /* Number of tables supported by datapath. */
uint8_t pad[3]; /* Align to 64-bits. */
/* Features. */
- uint32_t capabilities; /* Bitmap of support "ofp_capabilities". */
- uint32_t actions; /* Bitmap of supported "ofp_action_type"s. */
+ ovs_be32 capabilities; /* Bitmap of support "ofp_capabilities". */
+ ovs_be32 actions; /* Bitmap of supported "ofp_action_type"s. */
/* Port info.*/
struct ofp_phy_port ports[0]; /* Port definitions. The number of ports
/* Modify behavior of the physical port */
struct ofp_port_mod {
struct ofp_header header;
- uint16_t port_no;
+ ovs_be16 port_no;
uint8_t hw_addr[OFP_ETH_ALEN]; /* The hardware address is not
configurable. This is used to
sanity-check the request, so it must
be the same as returned in an
ofp_phy_port struct. */
- uint32_t config; /* Bitmap of OFPPC_* flags. */
- uint32_t mask; /* Bitmap of OFPPC_* flags to be changed. */
+ ovs_be32 config; /* Bitmap of OFPPC_* flags. */
+ ovs_be32 mask; /* Bitmap of OFPPC_* flags to be changed. */
- uint32_t advertise; /* Bitmap of "ofp_port_features"s. Zero all
+ ovs_be32 advertise; /* Bitmap of "ofp_port_features"s. Zero all
bits to prevent any action taking place. */
uint8_t pad[4]; /* Pad to 64-bits. */
};
/* Packet received on port (datapath -> controller). */
struct ofp_packet_in {
struct ofp_header header;
- uint32_t buffer_id; /* ID assigned by datapath. */
- uint16_t total_len; /* Full length of frame. */
- uint16_t in_port; /* Port on which frame was received. */
+ ovs_be32 buffer_id; /* ID assigned by datapath. */
+ ovs_be16 total_len; /* Full length of frame. */
+ ovs_be16 in_port; /* Port on which frame was received. */
uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */
uint8_t pad;
uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word,
* number of bytes to send. A 'max_len' of zero means no bytes of the
* packet should be sent. */
struct ofp_action_output {
- uint16_t type; /* OFPAT_OUTPUT. */
- uint16_t len; /* Length is 8. */
- uint16_t port; /* Output port. */
- uint16_t max_len; /* Max length to send to controller. */
+ ovs_be16 type; /* OFPAT_OUTPUT. */
+ ovs_be16 len; /* Length is 8. */
+ ovs_be16 port; /* Output port. */
+ ovs_be16 max_len; /* Max length to send to controller. */
};
OFP_ASSERT(sizeof(struct ofp_action_output) == 8);
/* Action structure for OFPAT_SET_VLAN_VID. */
struct ofp_action_vlan_vid {
- uint16_t type; /* OFPAT_SET_VLAN_VID. */
- uint16_t len; /* Length is 8. */
- uint16_t vlan_vid; /* VLAN id. */
+ ovs_be16 type; /* OFPAT_SET_VLAN_VID. */
+ ovs_be16 len; /* Length is 8. */
+ ovs_be16 vlan_vid; /* VLAN id. */
uint8_t pad[2];
};
OFP_ASSERT(sizeof(struct ofp_action_vlan_vid) == 8);
/* Action structure for OFPAT_SET_VLAN_PCP. */
struct ofp_action_vlan_pcp {
- uint16_t type; /* OFPAT_SET_VLAN_PCP. */
- uint16_t len; /* Length is 8. */
+ ovs_be16 type; /* OFPAT_SET_VLAN_PCP. */
+ ovs_be16 len; /* Length is 8. */
uint8_t vlan_pcp; /* VLAN priority. */
uint8_t pad[3];
};
/* Action structure for OFPAT_SET_DL_SRC/DST. */
struct ofp_action_dl_addr {
- uint16_t type; /* OFPAT_SET_DL_SRC/DST. */
- uint16_t len; /* Length is 16. */
+ ovs_be16 type; /* OFPAT_SET_DL_SRC/DST. */
+ ovs_be16 len; /* Length is 16. */
uint8_t dl_addr[OFP_ETH_ALEN]; /* Ethernet address. */
uint8_t pad[6];
};
/* Action structure for OFPAT_SET_NW_SRC/DST. */
struct ofp_action_nw_addr {
- uint16_t type; /* OFPAT_SET_TW_SRC/DST. */
- uint16_t len; /* Length is 8. */
- uint32_t nw_addr; /* IP address. */
+ ovs_be16 type; /* OFPAT_SET_TW_SRC/DST. */
+ ovs_be16 len; /* Length is 8. */
+ ovs_be32 nw_addr; /* IP address. */
};
OFP_ASSERT(sizeof(struct ofp_action_nw_addr) == 8);
/* Action structure for OFPAT_SET_NW_TOS. */
struct ofp_action_nw_tos {
- uint16_t type; /* OFPAT_SET_TW_TOS. */
- uint16_t len; /* Length is 8. */
+ ovs_be16 type; /* OFPAT_SET_TW_TOS. */
+ ovs_be16 len; /* Length is 8. */
uint8_t nw_tos; /* IP TOS (DSCP field, 6 bits). */
uint8_t pad[3];
};
/* Action structure for OFPAT_SET_TP_SRC/DST. */
struct ofp_action_tp_port {
- uint16_t type; /* OFPAT_SET_TP_SRC/DST. */
- uint16_t len; /* Length is 8. */
- uint16_t tp_port; /* TCP/UDP port. */
+ ovs_be16 type; /* OFPAT_SET_TP_SRC/DST. */
+ ovs_be16 len; /* Length is 8. */
+ ovs_be16 tp_port; /* TCP/UDP port. */
uint8_t pad[2];
};
OFP_ASSERT(sizeof(struct ofp_action_tp_port) == 8);
/* Action header for OFPAT_VENDOR. The rest of the body is vendor-defined. */
struct ofp_action_vendor_header {
- uint16_t type; /* OFPAT_VENDOR. */
- uint16_t len; /* Length is a multiple of 8. */
- uint32_t vendor; /* Vendor ID, which takes the same form
+ ovs_be16 type; /* OFPAT_VENDOR. */
+ ovs_be16 len; /* Length is a multiple of 8. */
+ ovs_be32 vendor; /* Vendor ID, which takes the same form
as in "struct ofp_vendor_header". */
};
OFP_ASSERT(sizeof(struct ofp_action_vendor_header) == 8);
* header and any padding used to make the action 64-bit aligned.
* NB: The length of an action *must* always be a multiple of eight. */
struct ofp_action_header {
- uint16_t type; /* One of OFPAT_*. */
- uint16_t len; /* Length of action, including this
+ ovs_be16 type; /* One of OFPAT_*. */
+ ovs_be16 len; /* Length of action, including this
header. This is the length of action,
including any padding to make it
64-bit aligned. */
/* OFPAT_ENQUEUE action struct: send packets to given queue on port. */
struct ofp_action_enqueue {
- uint16_t type; /* OFPAT_ENQUEUE. */
- uint16_t len; /* Len is 16. */
- uint16_t port; /* Port that queue belongs. Should
+ ovs_be16 type; /* OFPAT_ENQUEUE. */
+ ovs_be16 len; /* Len is 16. */
+ ovs_be16 port; /* Port that queue belongs. Should
refer to a valid physical port
(i.e. < OFPP_MAX) or OFPP_IN_PORT. */
uint8_t pad[6]; /* Pad for 64-bit alignment. */
- uint32_t queue_id; /* Where to enqueue the packets. */
+ ovs_be32 queue_id; /* Where to enqueue the packets. */
};
OFP_ASSERT(sizeof(struct ofp_action_enqueue) == 16);
union ofp_action {
- uint16_t type;
+ ovs_be16 type;
struct ofp_action_header header;
struct ofp_action_vendor_header vendor;
struct ofp_action_output output;
/* Send packet (controller -> datapath). */
struct ofp_packet_out {
struct ofp_header header;
- uint32_t buffer_id; /* ID assigned by datapath (-1 if none). */
- uint16_t in_port; /* Packet's input port (OFPP_NONE if none). */
- uint16_t actions_len; /* Size of action array in bytes. */
+ ovs_be32 buffer_id; /* ID assigned by datapath (-1 if none). */
+ ovs_be16 in_port; /* Packet's input port (OFPP_NONE if none). */
+ ovs_be16 actions_len; /* Size of action array in bytes. */
struct ofp_action_header actions[0]; /* Actions. */
/* uint8_t data[0]; */ /* Packet data. The length is inferred
from the length field in the header.
/* Fields to match against flows */
struct ofp_match {
- uint32_t wildcards; /* Wildcard fields. */
- uint16_t in_port; /* Input switch port. */
+ ovs_be32 wildcards; /* Wildcard fields. */
+ ovs_be16 in_port; /* Input switch port. */
uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */
uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */
- uint16_t dl_vlan; /* Input VLAN. */
+ ovs_be16 dl_vlan; /* Input VLAN. */
uint8_t dl_vlan_pcp; /* Input VLAN priority. */
uint8_t pad1[1]; /* Align to 64-bits. */
- uint16_t dl_type; /* Ethernet frame type. */
+ ovs_be16 dl_type; /* Ethernet frame type. */
uint8_t nw_tos; /* IP ToS (DSCP field, 6 bits). */
uint8_t nw_proto; /* IP protocol or lower 8 bits of
ARP opcode. */
uint8_t pad2[2]; /* Align to 64-bits. */
- uint32_t nw_src; /* IP source address. */
- uint32_t nw_dst; /* IP destination address. */
- uint16_t tp_src; /* TCP/UDP source port. */
- uint16_t tp_dst; /* TCP/UDP destination port. */
+ ovs_be32 nw_src; /* IP source address. */
+ ovs_be32 nw_dst; /* IP destination address. */
+ ovs_be16 tp_src; /* TCP/UDP source port. */
+ ovs_be16 tp_dst; /* TCP/UDP destination port. */
};
OFP_ASSERT(sizeof(struct ofp_match) == 40);
struct ofp_flow_mod {
struct ofp_header header;
struct ofp_match match; /* Fields to match */
- uint64_t cookie; /* Opaque controller-issued identifier. */
+ ovs_be64 cookie; /* Opaque controller-issued identifier. */
/* Flow actions. */
- uint16_t command; /* One of OFPFC_*. */
- uint16_t idle_timeout; /* Idle time before discarding (seconds). */
- uint16_t hard_timeout; /* Max time before discarding (seconds). */
- uint16_t priority; /* Priority level of flow entry. */
- uint32_t buffer_id; /* Buffered packet to apply to (or -1).
+ ovs_be16 command; /* One of OFPFC_*. */
+ ovs_be16 idle_timeout; /* Idle time before discarding (seconds). */
+ ovs_be16 hard_timeout; /* Max time before discarding (seconds). */
+ ovs_be16 priority; /* Priority level of flow entry. */
+ ovs_be32 buffer_id; /* Buffered packet to apply to (or -1).
Not meaningful for OFPFC_DELETE*. */
- uint16_t out_port; /* For OFPFC_DELETE* commands, require
+ ovs_be16 out_port; /* For OFPFC_DELETE* commands, require
matching entries to include this as an
output port. A value of OFPP_NONE
indicates no restriction. */
- uint16_t flags; /* One of OFPFF_*. */
+ ovs_be16 flags; /* One of OFPFF_*. */
struct ofp_action_header actions[0]; /* The action length is inferred
from the length field in the
header. */
struct ofp_flow_removed {
struct ofp_header header;
struct ofp_match match; /* Description of fields. */
- uint64_t cookie; /* Opaque controller-issued identifier. */
+ ovs_be64 cookie; /* Opaque controller-issued identifier. */
- uint16_t priority; /* Priority level of flow entry. */
+ ovs_be16 priority; /* Priority level of flow entry. */
uint8_t reason; /* One of OFPRR_*. */
uint8_t pad[1]; /* Align to 32-bits. */
- uint32_t duration_sec; /* Time flow was alive in seconds. */
- uint32_t duration_nsec; /* Time flow was alive in nanoseconds beyond
+ ovs_be32 duration_sec; /* Time flow was alive in seconds. */
+ ovs_be32 duration_nsec; /* Time flow was alive in nanoseconds beyond
duration_sec. */
- uint16_t idle_timeout; /* Idle timeout from original flow mod. */
+ ovs_be16 idle_timeout; /* Idle timeout from original flow mod. */
uint8_t pad2[2]; /* Align to 64-bits. */
- uint64_t packet_count;
- uint64_t byte_count;
+ ovs_be64 packet_count;
+ ovs_be64 byte_count;
};
OFP_ASSERT(sizeof(struct ofp_flow_removed) == 88);
struct ofp_error_msg {
struct ofp_header header;
- uint16_t type;
- uint16_t code;
+ ovs_be16 type;
+ ovs_be16 code;
uint8_t data[0]; /* Variable-length data. Interpreted based
on the type and code. */
};
struct ofp_stats_request {
struct ofp_header header;
- uint16_t type; /* One of the OFPST_* constants. */
- uint16_t flags; /* OFPSF_REQ_* flags (none yet defined). */
+ ovs_be16 type; /* One of the OFPST_* constants. */
+ ovs_be16 flags; /* OFPSF_REQ_* flags (none yet defined). */
uint8_t body[0]; /* Body of the request. */
};
OFP_ASSERT(sizeof(struct ofp_stats_request) == 12);
struct ofp_stats_reply {
struct ofp_header header;
- uint16_t type; /* One of the OFPST_* constants. */
- uint16_t flags; /* OFPSF_REPLY_* flags. */
+ ovs_be16 type; /* One of the OFPST_* constants. */
+ ovs_be16 flags; /* OFPSF_REPLY_* flags. */
uint8_t body[0]; /* Body of the reply. */
};
OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
uint8_t table_id; /* ID of table to read (from ofp_table_stats)
or 0xff for all tables. */
uint8_t pad; /* Align to 32 bits. */
- uint16_t out_port; /* Require matching entries to include this
+ ovs_be16 out_port; /* Require matching entries to include this
as an output port. A value of OFPP_NONE
indicates no restriction. */
};
/* Body of reply to OFPST_FLOW request. */
struct ofp_flow_stats {
- uint16_t length; /* Length of this entry. */
+ ovs_be16 length; /* Length of this entry. */
uint8_t table_id; /* ID of table flow came from. */
uint8_t pad;
struct ofp_match match; /* Description of fields. */
- uint32_t duration_sec; /* Time flow has been alive in seconds. */
- uint32_t duration_nsec; /* Time flow has been alive in nanoseconds
+ ovs_be32 duration_sec; /* Time flow has been alive in seconds. */
+ ovs_be32 duration_nsec; /* Time flow has been alive in nanoseconds
beyond duration_sec. */
- uint16_t priority; /* Priority of the entry. Only meaningful
+ ovs_be16 priority; /* Priority of the entry. Only meaningful
when this is not an exact-match entry. */
- uint16_t idle_timeout; /* Number of seconds idle before expiration. */
- uint16_t hard_timeout; /* Number of seconds before expiration. */
+ ovs_be16 idle_timeout; /* Number of seconds idle before expiration. */
+ ovs_be16 hard_timeout; /* Number of seconds before expiration. */
uint8_t pad2[6]; /* Align to 64 bits. */
ovs_32aligned_be64 cookie; /* Opaque controller-issued identifier. */
ovs_32aligned_be64 packet_count; /* Number of packets in flow. */
uint8_t table_id; /* ID of table to read (from ofp_table_stats)
or 0xff for all tables. */
uint8_t pad; /* Align to 32 bits. */
- uint16_t out_port; /* Require matching entries to include this
+ ovs_be16 out_port; /* Require matching entries to include this
as an output port. A value of OFPP_NONE
indicates no restriction. */
};
struct ofp_aggregate_stats_reply {
ovs_32aligned_be64 packet_count; /* Number of packets in flows. */
ovs_32aligned_be64 byte_count; /* Number of bytes in flows. */
- uint32_t flow_count; /* Number of flows. */
+ ovs_be32 flow_count; /* Number of flows. */
uint8_t pad[4]; /* Align to 64 bits. */
};
OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
are consulted first. */
uint8_t pad[3]; /* Align to 32-bits. */
char name[OFP_MAX_TABLE_NAME_LEN];
- uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are
+ ovs_be32 wildcards; /* Bitmap of OFPFW_* wildcards that are
supported by the table. */
- uint32_t max_entries; /* Max number of entries supported. */
- uint32_t active_count; /* Number of active entries. */
+ ovs_be32 max_entries; /* Max number of entries supported. */
+ ovs_be32 active_count; /* Number of active entries. */
ovs_32aligned_be64 lookup_count; /* # of packets looked up in table. */
ovs_32aligned_be64 matched_count; /* Number of packets that hit table. */
};
/* Body for ofp_stats_request of type OFPST_PORT. */
struct ofp_port_stats_request {
- uint16_t port_no; /* OFPST_PORT message may request statistics
+ ovs_be16 port_no; /* OFPST_PORT message may request statistics
for a single port (specified with port_no)
or for all ports (port_no == OFPP_NONE). */
uint8_t pad[6];
/* Body of reply to OFPST_PORT request. If a counter is unsupported, set
* the field to all ones. */
struct ofp_port_stats {
- uint16_t port_no;
+ ovs_be16 port_no;
uint8_t pad[6]; /* Align to 64-bits. */
ovs_32aligned_be64 rx_packets; /* Number of received packets. */
ovs_32aligned_be64 tx_packets; /* Number of transmitted packets. */
/* Body for ofp_stats_request of type OFPST_QUEUE. */
struct ofp_queue_stats_request {
- uint16_t port_no; /* All ports if OFPP_ALL. */
+ ovs_be16 port_no; /* All ports if OFPP_ALL. */
uint8_t pad[2]; /* Align to 32-bits. */
- uint32_t queue_id; /* All queues if OFPQ_ALL. */
+ ovs_be32 queue_id; /* All queues if OFPQ_ALL. */
};
OFP_ASSERT(sizeof(struct ofp_queue_stats_request) == 8);
/* Body for ofp_stats_reply of type OFPST_QUEUE consists of an array of this
* structure type. */
struct ofp_queue_stats {
- uint16_t port_no;
+ ovs_be16 port_no;
uint8_t pad[2]; /* Align to 32-bits. */
- uint32_t queue_id; /* Queue id. */
+ ovs_be32 queue_id; /* Queue id. */
ovs_32aligned_be64 tx_bytes; /* Number of transmitted bytes. */
ovs_32aligned_be64 tx_packets; /* Number of transmitted packets. */
ovs_32aligned_be64 tx_errors; /* # of packets dropped due to overrun. */
/* Vendor extension. */
struct ofp_vendor_header {
struct ofp_header header; /* Type OFPT_VENDOR. */
- uint32_t vendor; /* Vendor ID:
+ ovs_be32 vendor; /* Vendor ID:
* - MSB 0: low-order bytes are IEEE OUI.
* - MSB != 0: defined by OpenFlow
* consortium. */
#ifndef OPENVSWITCH_TYPES_H
#define OPENVSWITCH_TYPES_H 1
-#include <arpa/inet.h>
#include <sys/types.h>
#include <stdint.h>
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHECKER__
+#error "Use this header only with sparse. It is not a correct implementation."
+#endif
+
+#include <netinet/in.h>
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHECKER__
+#error "Use this header only with sparse. It is not a correct implementation."
+#endif
+
+extern void __ovs_assert(_Bool);
+#define assert(EXPRESSION) __ovs_assert(EXPRESSION)
--- /dev/null
+noinst_HEADERS += \
+ include/sparse/arpa/inet.h \
+ include/sparse/assert.h \
+ include/sparse/math.h \
+ include/sparse/netinet/in.h \
+ include/sparse/netinet/ip6.h \
+ include/sparse/sys/socket.h \
+ include/sparse/sys/wait.h
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHECKER__
+#error "Use this header only with sparse. It is not a correct implementation."
+#endif
+
+#ifndef __SYS_MATH_SPARSE
+#define __SYS_MATH_SPARSE 1
+
+double acos(double);
+float acosf(float);
+double acosh(double);
+float acoshf(float);
+long double acoshl(long double);
+long double acosl(long double);
+double asin(double);
+float asinf(float);
+double asinh(double);
+float asinhf(float);
+long double asinhl(long double);
+long double asinl(long double);
+double atan(double);
+double atan2(double, double);
+float atan2f(float, float);
+long double atan2l(long double, long double);
+float atanf(float);
+double atanh(double);
+float atanhf(float);
+long double atanhl(long double);
+long double atanl(long double);
+double cbrt(double);
+float cbrtf(float);
+long double cbrtl(long double);
+double ceil(double);
+float ceilf(float);
+long double ceill(long double);
+double copysign(double, double);
+float copysignf(float, float);
+long double copysignl(long double, long double);
+double cos(double);
+float cosf(float);
+double cosh(double);
+float coshf(float);
+long double coshl(long double);
+long double cosl(long double);
+double erf(double);
+double erfc(double);
+float erfcf(float);
+long double erfcl(long double);
+float erff(float);
+long double erfl(long double);
+double exp(double);
+double exp2(double);
+float exp2f(float);
+long double exp2l(long double);
+float expf(float);
+long double expl(long double);
+double expm1(double);
+float expm1f(float);
+long double expm1l(long double);
+double fabs(double);
+float fabsf(float);
+long double fabsl(long double);
+double fdim(double, double);
+float fdimf(float, float);
+long double fdiml(long double, long double);
+double floor(double);
+float floorf(float);
+long double floorl(long double);
+double fma(double, double, double);
+float fmaf(float, float, float);
+long double fmal(long double, long double, long double);
+double fmax(double, double);
+float fmaxf(float, float);
+long double fmaxl(long double, long double);
+double fmin(double, double);
+float fminf(float, float);
+long double fminl(long double, long double);
+double fmod(double, double);
+float fmodf(float, float);
+long double fmodl(long double, long double);
+double frexp(double, int *);
+float frexpf(float value, int *);
+long double frexpl(long double value, int *);
+double hypot(double, double);
+float hypotf(float, float);
+long double hypotl(long double, long double);
+int ilogb(double);
+int ilogbf(float);
+int ilogbl(long double);
+double j0(double);
+double j1(double);
+double jn(int, double);
+double ldexp(double, int);
+float ldexpf(float, int);
+long double ldexpl(long double, int);
+double lgamma(double);
+float lgammaf(float);
+long double lgammal(long double);
+long long llrint(double);
+long long llrintf(float);
+long long llrintl(long double);
+long long llround(double);
+long long llroundf(float);
+long long llroundl(long double);
+double log(double);
+double log10(double);
+float log10f(float);
+long double log10l(long double);
+double log1p(double);
+float log1pf(float);
+long double log1pl(long double);
+double log2(double);
+float log2f(float);
+long double log2l(long double);
+double logb(double);
+float logbf(float);
+long double logbl(long double);
+float logf(float);
+long double logl(long double);
+long lrint(double);
+long lrintf(float);
+long lrintl(long double);
+long lround(double);
+long lroundf(float);
+long lroundl(long double);
+double modf(double, double *);
+float modff(float, float *);
+long double modfl(long double, long double *);
+double nan(const char *);
+float nanf(const char *);
+long double nanl(const char *);
+double nearbyint(double);
+float nearbyintf(float);
+long double nearbyintl(long double);
+double nextafter(double, double);
+float nextafterf(float, float);
+long double nextafterl(long double, long double);
+double nexttoward(double, long double);
+float nexttowardf(float, long double);
+long double nexttowardl(long double, long double);
+double pow(double, double);
+float powf(float, float);
+long double powl(long double, long double);
+double remainder(double, double);
+float remainderf(float, float);
+long double remainderl(long double, long double);
+double remquo(double, double, int *);
+float remquof(float, float, int *);
+long double remquol(long double, long double, int *);
+double rint(double);
+float rintf(float);
+long double rintl(long double);
+double round(double);
+float roundf(float);
+long double roundl(long double);
+double scalb(double, double);
+double scalbln(double, long);
+float scalblnf(float, long);
+long double scalblnl(long double, long);
+double scalbn(double, int);
+float scalbnf(float, int);
+long double scalbnl(long double, int);
+double sin(double);
+float sinf(float);
+double sinh(double);
+float sinhf(float);
+long double sinhl(long double);
+long double sinl(long double);
+double sqrt(double);
+float sqrtf(float);
+long double sqrtl(long double);
+double tan(double);
+float tanf(float);
+double tanh(double);
+float tanhf(float);
+long double tanhl(long double);
+long double tanl(long double);
+double tgamma(double);
+float tgammaf(float);
+long double tgammal(long double);
+double trunc(double);
+float truncf(float);
+long double truncl(long double);
+double y0(double);
+double y1(double);
+double yn(int, double);
+
+#endif /* <sys/math.h> for sparse */
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHECKER__
+#error "Use this header only with sparse. It is not a correct implementation."
+#endif
+
+#ifndef __NETINET_IN_SPARSE
+#define __NETINET_IN_SPARSE 1
+
+#include "openvswitch/types.h"
+#include <inttypes.h>
+#include <sys/socket.h>
+
+typedef ovs_be16 in_port_t;
+typedef ovs_be32 in_addr_t;
+
+struct in_addr {
+ in_addr_t s_addr;
+};
+
+struct sockaddr_in {
+ sa_family_t sin_family;
+ in_port_t sin_port;
+ struct in_addr sin_addr;
+};
+
+struct in6_addr {
+ union {
+ uint8_t u_s6_addr[16];
+ } u;
+};
+
+#define s6_addr u.u_s6_addr
+
+extern const struct in6_addr in6addr_any;
+
+#define IPPROTO_IP 0
+#define IPPROTO_HOPOPTS 0
+#define IPPROTO_ICMP 1
+#define IPPROTO_TCP 6
+#define IPPROTO_UDP 17
+#define IPPROTO_ROUTING 43
+#define IPPROTO_FRAGMENT 44
+#define IPPROTO_AH 51
+#define IPPROTO_ICMPV6 58
+#define IPPROTO_NONE 59
+#define IPPROTO_DSTOPTS 60
+
+#define INADDR_ANY 0x00000000
+#define INADDR_BROADCAST 0xffffffff
+#define INADDR_NONE 0xffffffff
+
+#define INET6_ADDRSTRLEN 46
+
+static inline ovs_be32 htonl(uint32_t x)
+{
+ return (OVS_FORCE ovs_be32) x;
+}
+
+static inline ovs_be16 htons(uint16_t x)
+{
+ return (OVS_FORCE ovs_be16) x;
+}
+
+static inline uint32_t ntohl(ovs_be32 x)
+{
+ return (OVS_FORCE uint32_t) x;
+}
+
+static inline uint16_t ntohs(ovs_be16 x)
+{
+ return (OVS_FORCE uint16_t) x;
+}
+
+in_addr_t inet_addr(const char *);
+int inet_aton (const char *, struct in_addr *);
+char *inet_ntoa(struct in_addr);
+const char *inet_ntop(int, const void *, char *, socklen_t);
+int inet_pton(int, const char *, void *);
+
+#endif /* <netinet/in.h> sparse */
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHECKER__
+#error "Use this header only with sparse. It is not a correct implementation."
+#endif
+
+#ifndef __NETINET_IP6_SPARSE
+#define __NETINET_IP6_SPARSE 1
+
+#include <netinet/in.h>
+
+struct ip6_hdr {
+ union {
+ struct ip6_hdrctl {
+ ovs_be32 ip6_un1_flow;
+ ovs_be16 ip6_un1_plen;
+ uint8_t ip6_un1_nxt;
+ uint8_t ip6_un1_hlim;
+ } ip6_un1;
+ uint8_t ip6_un2_vfc;
+ } ip6_ctlun;
+ struct in6_addr ip6_src;
+ struct in6_addr ip6_dst;
+};
+
+#define ip6_vfc ip6_ctlun.ip6_un2_vfc
+#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+struct ip6_ext {
+ uint8_t ip6e_nxt;
+ uint8_t ip6e_len;
+};
+
+struct ip6_frag {
+ uint8_t ip6f_nxt;
+ uint8_t ip6f_reserved;
+ ovs_be16 ip6f_offlg;
+ ovs_be32 ip6f_ident;
+};
+
+#define IP6F_OFF_MASK ((OVS_FORCE ovs_be16) 0xfff8)
+
+#endif /* netinet/ip6.h sparse */
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHECKER__
+#error "Use this header only with sparse. It is not a correct implementation."
+#endif
+
+#ifndef __SYS_SOCKET_SPARSE
+#define __SYS_SOCKET_SPARSE 1
+
+#include "openvswitch/types.h"
+#include <sys/uio.h>
+
+typedef unsigned short int sa_family_t;
+typedef __socklen_t socklen_t;
+
+struct sockaddr {
+ sa_family_t sa_family;
+ char sa_data[64];
+};
+
+struct sockaddr_storage {
+ sa_family_t ss_family;
+ char sa_data[64];
+};
+
+struct msghdr {
+ void *msg_name;
+ socklen_t msg_namelen;
+ struct iovec *msg_iov;
+ int msg_iovlen;
+ void *msg_control;
+ socklen_t msg_controllen;
+ int msg_flags;
+};
+
+enum {
+ SOCK_DGRAM,
+ SOCK_RAW,
+ SOCK_SEQPACKET,
+ SOCK_STREAM
+};
+
+enum {
+ SOL_SOCKET
+};
+
+enum {
+ SO_ACCEPTCONN,
+ SO_BROADCAST,
+ SO_DEBUG,
+ SO_DONTROUTE,
+ SO_ERROR,
+ SO_KEEPALIVE,
+ SO_LINGER,
+ SO_OOBINLINE,
+ SO_RCVBUF,
+ SO_RCVLOWAT,
+ SO_RCVTIMEO,
+ SO_REUSEADDR,
+ SO_SNDBUF,
+ SO_SNDLOWAT,
+ SO_SNDTIMEO,
+ SO_TYPE
+};
+
+enum {
+ MSG_CTRUNC,
+ MSG_DONTROUTE,
+ MSG_EOR,
+ MSG_OOB,
+ MSG_NOSIGNAL,
+ MSG_PEEK,
+ MSG_TRUNC,
+ MSG_WAITALL,
+ MSG_DONTWAIT
+};
+
+enum {
+ AF_UNSPEC,
+ PF_UNSPEC = AF_UNSPEC,
+ AF_INET,
+ PF_INET = AF_INET,
+ AF_INET6,
+ PF_INET6 = AF_INET6,
+ AF_UNIX,
+ PF_UNIX = AF_UNIX,
+ AF_NETLINK,
+ PF_NETLINK = AF_NETLINK,
+ AF_PACKET,
+ PF_PACKET = AF_PACKET
+};
+
+enum {
+ SHUT_RD,
+ SHUT_RDWR,
+ SHUT_WR
+};
+
+int accept(int, struct sockaddr *, socklen_t *);
+int bind(int, const struct sockaddr *, socklen_t);
+int connect(int, const struct sockaddr *, socklen_t);
+int getpeername(int, struct sockaddr *, socklen_t *);
+int getsockname(int, struct sockaddr *, socklen_t *);
+int getsockopt(int, int, int, void *, socklen_t *);
+int listen(int, int);
+ssize_t recv(int, void *, size_t, int);
+ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
+ssize_t recvmsg(int, struct msghdr *, int);
+ssize_t send(int, const void *, size_t, int);
+ssize_t sendmsg(int, const struct msghdr *, int);
+ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *,
+ socklen_t);
+int setsockopt(int, int, int, const void *, socklen_t);
+int shutdown(int, int);
+int sockatmark(int);
+int socket(int, int, int);
+int socketpair(int, int, int, int[2]);
+
+#endif /* <sys/socket.h> for sparse */
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CHECKER__
+#error "Use this header only with sparse. It is not a correct implementation."
+#endif
+
+#ifndef __SYS_WAIT_SPARSE
+#define __SYS_WAIT_SPARSE 1
+
+#include_next <sys/wait.h>
+
+#undef wait
+#define wait(a) rpl_wait(a)
+pid_t rpl_wait(int *);
+
+#undef waitpid
+#define waitpid(a, b, c) rpl_waitpid(a, b, c)
+pid_t rpl_waitpid(pid_t, int *, int);
+
+#endif /* <sys/wait.h> for sparse */
/*
- * 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 <config.h>
+
#include "backtrace.h"
+
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
+
#include "compiler.h"
#include "vlog.h"
VLOG_DEFINE_THIS_MODULE(backtrace);
-static uintptr_t OVS_UNUSED
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+void
+backtrace_capture(struct backtrace *b)
+{
+ void *frames[BACKTRACE_MAX_FRAMES];
+ int i;
+
+ b->n_frames = backtrace(frames, BACKTRACE_MAX_FRAMES);
+ for (i = 0; i < b->n_frames; i++) {
+ b->frames[i] = (uintptr_t) frames[i];
+ }
+}
+#elif __GNUC__
+static uintptr_t
get_max_stack(void)
{
static const char file_name[] = "/proc/self/maps";
void
backtrace_capture(struct backtrace *backtrace)
{
-#ifdef __GNUC__
void **frame;
size_t n;
backtrace->frames[n++] = (uintptr_t) frame[1];
}
backtrace->n_frames = n;
-#else
+}
+#else /* !HAVE_BACKTRACE && !__GNUC__ */
+void
+backtrace_capture(struct backtrace *backtrace)
+{
backtrace->n_frames = 0;
-#endif
}
+#endif
bond->miimon_next_update = time_msec() + bond->miimon_interval;
}
+ if (bond->monitor) {
+ netdev_monitor_flush(bond->monitor);
+ }
+
/* Enable slaves based on link status and LACP feedback. */
HMAP_FOR_EACH (slave, hmap_node, &bond->slaves) {
bond_link_status_update(slave, tags);
bond_hash_tcp(const struct flow *flow, uint16_t vlan, uint32_t basis)
{
struct flow hash_flow = *flow;
- hash_flow.vlan_tci = vlan;
+ hash_flow.vlan_tci = htons(vlan);
/* The symmetric quality of this hash function is not required, but
* flow_hash_symmetric_l4 already exists, and is sufficient for our
#include <inttypes.h>
#include "openvswitch/types.h"
+#ifndef __CHECKER__
static inline ovs_be64
htonll(uint64_t n)
{
{
return htonl(1) == 1 ? n : ((uint64_t) ntohl(n) << 32) | ntohl(n >> 32);
}
+#else
+/* Making sparse happy with these functions also makes them unreadable, so
+ * don't bother to show it their implementations. */
+ovs_be64 htonll(uint64_t);
+uint64_t ntohll(ovs_be64);
+#endif
/* These macros may substitute for htons(), htonl(), and htonll() in contexts
* where function calls are not allowed, such as case labels. They should not
* be used elsewhere because all of them evaluate their argument many times. */
-#ifdef WORDS_BIGENDIAN
-#define CONSTANT_HTONS(VALUE) ((ovs_be16) (VALUE))
-#define CONSTANT_HTONL(VALUE) ((ovs_be32) (VALUE))
-#define CONSTANT_HTONLL(VALUE) ((ovs_be64) (VALUE))
+#if defined(WORDS_BIGENDIAN) || __CHECKER__
+#define CONSTANT_HTONS(VALUE) ((OVS_FORCE ovs_be16) ((VALUE) & 0xffff))
+#define CONSTANT_HTONL(VALUE) ((OVS_FORCE ovs_be32) ((VALUE) & 0xffffffff))
+#define CONSTANT_HTONLL(VALUE) \
+ ((OVS_FORCE ovs_be64) ((VALUE) & UINT64_C(0xffffffffffffffff)))
#else
#define CONSTANT_HTONS(VALUE) \
(((((ovs_be16) (VALUE)) & 0xff00) >> 8) | \
struct timer tx_timer; /* Send CCM when expired. */
struct timer fault_timer; /* Check for faults when expired. */
-
- long long x_recv_time;
};
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+
static int
ccm_interval_to_ms(uint8_t interval)
{
}
/* Allocates a 'cfm' object. This object should have its 'mpid', 'maid',
- * 'eth_src', and 'interval' filled out. When changes are made to the 'cfm'
- * object, cfm_configure should be called before using it. */
+ * 'eth_src', and 'interval' filled out. cfm_configure() should be called
+ * whenever changes are made to 'cfm', and before cfm_run() is called for the
+ * first time. */
struct cfm *
cfm_create(void)
{
cfmi = xzalloc(sizeof *cfmi);
cfm = &cfmi->cfm;
- cfmi->x_recv_time = LLONG_MIN;
hmap_init(&cfm->remote_mps);
return cfm;
void
cfm_run(struct cfm *cfm)
{
- long long now = time_msec();
struct cfm_internal *cfmi = cfm_to_internal(cfm);
if (timer_expired(&cfmi->fault_timer)) {
- bool fault;
+ long long int interval = cfm_fault_interval(cfmi);
struct remote_mp *rmp;
- long long int interval;
-
- interval = cfm_fault_interval(cfmi);
- fault = now < cfmi->x_recv_time + interval;
+ cfm->fault = false;
HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) {
- if (rmp->recv_time < timer_enabled_at(&cfmi->fault_timer, interval)
- || timer_expired_at(&cfmi->fault_timer, rmp->recv_time)) {
- rmp->fault = true;
- }
+ rmp->fault = !rmp->recv;
+ rmp->recv = false;
if (rmp->fault) {
- fault = true;
+ cfm->fault = true;
+ VLOG_DBG("No CCM from RMP %"PRIu16" in the last %lldms",
+ rmp->mpid, interval);
}
}
- cfm->fault = fault;
+ if (!cfm->fault) {
+ VLOG_DBG("All RMPs received CCMs in the last %lldms", interval);
+ }
+
timer_set_duration(&cfmi->fault_timer, interval);
}
}
uint8_t ccm_interval;
struct remote_mp *rmp;
struct eth_header *eth;
-
- struct cfm_internal *cfmi = cfm_to_internal(cfm);
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+ struct cfm_internal *cfmi = cfm_to_internal(cfm);
eth = p->l2;
ccm = ofpbuf_at(p, (uint8_t *)p->l3 - (uint8_t *)p->data, CCM_LEN);
return;
}
+ /* According to the 802.1ag specification, reception of a CCM with an
+ * incorrect ccm_interval, unexpected MAID, or unexpected MPID should
+ * trigger a fault. We ignore this requirement for several reasons.
+ *
+ * Faults can cause a controller or Open vSwitch to make potentially
+ * expensive changes to the network topology. It seems prudent to trigger
+ * them judiciously, especially when CFM is used to check slave status of
+ * bonds. Furthermore, faults can be maliciously triggered by crafting
+ * invalid CCMs. */
if (memcmp(ccm->maid, cfm->maid, sizeof ccm->maid)) {
- cfmi->x_recv_time = time_msec();
- cfm->fault = true;
VLOG_WARN_RL(&rl, "Received unexpected remote MAID from MAC "
ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_src));
} else {
rmp = lookup_remote_mp(&cfm->remote_mps, ccm_mpid);
if (rmp) {
- rmp->recv_time = time_msec();
- rmp->fault = ccm_interval != cfmi->ccm_interval;
- cfm->fault = rmp->fault || cfm->fault;
+ rmp->recv = true;
+
+ if (ccm_interval != cfmi->ccm_interval) {
+ VLOG_WARN_RL(&rl, "received a CCM with an invalid interval"
+ " (%"PRIu8") from RMP %"PRIu16, ccm_interval,
+ rmp->mpid);
+ }
} else {
- cfmi->x_recv_time = time_msec();
- cfm->fault = true;
VLOG_WARN_RL(&rl, "Received unexpected remote MPID %d from MAC "
ETH_ADDR_FMT, ccm_mpid, ETH_ADDR_ARGS(eth->eth_src));
}
+
+ VLOG_DBG("Received CCM (mpid %"PRIu16") (interval %"PRIu8")", ccm_mpid,
+ ccm_interval);
}
}
cfm_dump_ds(const struct cfm *cfm, struct ds *ds)
{
const struct cfm_internal *cfmi = cfm_to_internal(cfm);
- long long int now = time_msec();
struct remote_mp *rmp;
ds_put_format(ds, "MPID %"PRIu16": %s\n", cfm->mpid,
ds_put_format(ds, "\tnext fault check: %lldms\n",
timer_msecs_until_expired(&cfmi->fault_timer));
- if (cfmi->x_recv_time != LLONG_MIN) {
- ds_put_format(ds, "\ttime since bad CCM rx: %lldms\n",
- now - cfmi->x_recv_time);
- }
-
ds_put_cstr(ds, "\n");
HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) {
ds_put_format(ds, "Remote MPID %"PRIu16": %s\n", rmp->mpid,
rmp->fault ? "fault" : "");
- ds_put_format(ds, "\ttime since CCM rx: %lldms\n",
- time_msec() - rmp->recv_time);
+ ds_put_format(ds, "\trecv since check: %s",
+ rmp->recv ? "true" : "false");
}
}
uint16_t mpid; /* The Maintenance Point ID of this 'remote_mp'. */
struct hmap_node node; /* In 'cfm' 'remote_mps' or 'x_remote_mps'. */
- long long recv_time; /* Time the most recent CCM was received. */
+ bool recv; /* CCM was received since last fault check. */
bool fault; /* Indicates a connectivity fault. */
};
/*
- * 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.
#ifndef COMPILER_H
#define COMPILER_H 1
-#ifdef __GNUC__
+#if __GNUC__ && !__CHECKER__
#define NO_RETURN __attribute__((__noreturn__))
#define OVS_UNUSED __attribute__((__unused__))
#define PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 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.
#if USE_LINKER_SECTIONS
#define COVERAGE_DEFINE(COUNTER) \
COVERAGE_DEFINE__(COUNTER); \
+ extern struct coverage_counter *counter_ptr_##COUNTER; \
struct coverage_counter *counter_ptr_##COUNTER \
__attribute__((section("coverage"))) = &counter_##COUNTER
#else
/* Implementation detail. */
#define COVERAGE_DEFINE__(COUNTER) \
+ extern struct coverage_counter counter_##COUNTER; \
struct coverage_counter counter_##COUNTER = { #COUNTER, 0, 0 }
#endif /* coverage.h */
/*
- * 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 "csum.h"
#include "unaligned.h"
+#ifndef __CHECKER__
+
/* Returns the IP checksum of the 'n' bytes in 'data'.
*
* The return value has the same endianness as the data. That is, if 'data'
* consists of a packet in network byte order, then the return value is a value
* in network byte order, and if 'data' consists of a data structure in host
* byte order, then the return value is in host byte order. */
-uint16_t
+ovs_be16
csum(const void *data, size_t n)
{
return csum_finish(csum_continue(0, data, n));
* the updated checksum. (To start a new checksum, pass 0 for 'partial'. To
* obtain the finished checksum, pass the return value to csum_finish().) */
uint32_t
-csum_add16(uint32_t partial, uint16_t new)
+csum_add16(uint32_t partial, ovs_be16 new)
{
return partial + new;
}
* the updated checksum. (To start a new checksum, pass 0 for 'partial'. To
* obtain the finished checksum, pass the return value to csum_finish().) */
uint32_t
-csum_add32(uint32_t partial, uint32_t new)
+csum_add32(uint32_t partial, ovs_be32 new)
{
return partial + (new >> 16) + (new & 0xffff);
}
uint32_t
csum_continue(uint32_t partial, const void *data_, size_t n)
{
- const uint16_t *data = data_;
+ const ovs_be16 *data = data_;
for (; n > 1; n -= 2, data++) {
- partial = csum_add16(partial, get_unaligned_u16(data));
+ partial = csum_add16(partial, get_unaligned_be16(data));
}
if (n) {
partial += *(uint8_t *) data;
* if the data consist of a packet in network byte order, then the return value
* is a value in network byte order, and if the data are a data structure in
* host byte order, then the return value is in host byte order. */
-uint16_t
+ovs_be16
csum_finish(uint32_t partial)
{
while (partial >> 16) {
/* Returns the new checksum for a packet in which the checksum field previously
* contained 'old_csum' and in which a field that contained 'old_u16' was
* changed to contain 'new_u16'. */
-uint16_t
-recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16)
+ovs_be16
+recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 new_u16)
{
/* Ones-complement arithmetic is endian-independent, so this code does not
* use htons() or ntohs().
/* Returns the new checksum for a packet in which the checksum field previously
* contained 'old_csum' and in which a field that contained 'old_u32' was
* changed to contain 'new_u32'. */
-uint16_t
-recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32)
+ovs_be16
+recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32)
{
return recalc_csum16(recalc_csum16(old_csum, old_u32, new_u32),
old_u32 >> 16, new_u32 >> 16);
}
+
+#else /* __CHECKER__ */
+/* Making sparse happy with these functions also makes them unreadable, so
+ * don't bother to show it their implementations. */
+#endif
/*
- * Copyright (c) 2008 Nicira Networks.
+ * Copyright (c) 2008, 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 <stddef.h>
#include <stdint.h>
+#include "openvswitch/types.h"
-uint16_t csum(const void *, size_t);
-uint32_t csum_add16(uint32_t partial, uint16_t);
-uint32_t csum_add32(uint32_t partial, uint32_t);
+ovs_be16 csum(const void *, size_t);
+uint32_t csum_add16(uint32_t partial, ovs_be16);
+uint32_t csum_add32(uint32_t partial, ovs_be32);
uint32_t csum_continue(uint32_t partial, const void *, size_t);
-uint16_t csum_finish(uint32_t partial);
-uint16_t recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16);
-uint16_t recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32);
+ovs_be16 csum_finish(uint32_t partial);
+ovs_be16 recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 new_u16);
+ovs_be16 recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32);
#endif /* csum.h */
OPT_PIDFILE, \
OPT_MONITOR
-#define DAEMON_LONG_OPTIONS \
- {"detach", no_argument, 0, OPT_DETACH}, \
- {"no-chdir", no_argument, 0, OPT_NO_CHDIR}, \
- {"pidfile", optional_argument, 0, OPT_PIDFILE}, \
- {"overwrite-pidfile", no_argument, 0, OPT_OVERWRITE_PIDFILE},\
- {"monitor", no_argument, 0, OPT_MONITOR}
+#define DAEMON_LONG_OPTIONS \
+ {"detach", no_argument, NULL, OPT_DETACH}, \
+ {"no-chdir", no_argument, NULL, OPT_NO_CHDIR}, \
+ {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \
+ {"overwrite-pidfile", no_argument, NULL, OPT_OVERWRITE_PIDFILE}, \
+ {"monitor", no_argument, NULL, OPT_MONITOR}
#define DAEMON_OPTION_HANDLERS \
case OPT_DETACH: \
}
/* Clears 'dp' to "empty" values. */
-void
+static void
dpif_linux_dp_init(struct dpif_linux_dp *dp)
{
memset(dp, 0, sizeof *dp);
* result of the command is expected to be of the same form, which is decoded
* and stored in '*reply' and '*bufp'. The caller must free '*bufp' when the
* reply is no longer needed ('reply' will contain pointers into '*bufp'). */
-int
+static int
dpif_linux_dp_transact(const struct dpif_linux_dp *request,
struct dpif_linux_dp *reply, struct ofpbuf **bufp)
{
/* Obtains information about 'dpif_' and stores it into '*reply' and '*bufp'.
* The caller must free '*bufp' when the reply is no longer needed ('reply'
* will contain pointers into '*bufp'). */
-int
+static int
dpif_linux_dp_get(const struct dpif *dpif_, struct dpif_linux_dp *reply,
struct ofpbuf **bufp)
{
}
/* Clears 'flow' to "empty" values. */
-void
+static void
dpif_linux_flow_init(struct dpif_linux_flow *flow)
{
memset(flow, 0, sizeof *flow);
* result of the command is expected to be a flow also, which is decoded and
* stored in '*reply' and '*bufp'. The caller must free '*bufp' when the reply
* is no longer needed ('reply' will contain pointers into '*bufp'). */
-int
+static int
dpif_linux_flow_transact(const struct dpif_linux_flow *request,
struct dpif_linux_flow *reply, struct ofpbuf **bufp)
{
long long int used; /* Last used time, in monotonic msecs. */
long long int packet_count; /* Number of packets matched. */
long long int byte_count; /* Number of bytes matched. */
- uint16_t tcp_ctl; /* Bitwise-OR of seen tcp_ctl values. */
+ ovs_be16 tcp_ctl; /* Bitwise-OR of seen tcp_ctl values. */
/* Actions. */
struct nlattr *actions;
struct ip_header *nh = packet->l3;
ovs_be32 ip = nl_attr_get_be32(a);
uint16_t type = nl_attr_type(a);
- uint32_t *field;
+ ovs_be32 *field;
field = type == ODP_ACTION_ATTR_SET_NW_SRC ? &nh->ip_src : &nh->ip_dst;
if (key->nw_proto == IPPROTO_TCP && packet->l7) {
if (uh->udp_csum) {
uh->udp_csum = recalc_csum32(uh->udp_csum, *field, ip);
if (!uh->udp_csum) {
- uh->udp_csum = 0xffff;
+ uh->udp_csum = htons(0xffff);
}
}
}
if (is_ip(packet, key)) {
uint16_t type = nl_attr_type(a);
ovs_be16 port = nl_attr_get_be16(a);
- uint16_t *field;
+ ovs_be16 *field;
if (key->nw_proto == IPPROTO_TCP && packet->l7) {
struct tcp_header *th = packet->l4;
}
for (i = 0; i < FLOW_N_REGS; i++) {
- if (wc->reg_masks[i] != htonl(UINT32_MAX)) {
+ if (wc->reg_masks[i] != UINT32_MAX) {
return false;
}
}
BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->nd_target) == 16);
BUILD_ASSERT_DECL(sizeof(struct flow) == FLOW_SIG_SIZE + FLOW_PAD_SIZE);
-int flow_extract(struct ofpbuf *, uint64_t tun_id, uint16_t in_port,
+int flow_extract(struct ofpbuf *, ovs_be64 tun_id, uint16_t in_port,
struct flow *);
void flow_extract_stats(const struct flow *flow, struct ofpbuf *packet,
struct dpif_flow_stats *);
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 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 <errno.h>
#include <float.h>
#include <limits.h>
-#include <math.h>
#include <string.h>
#include "dynamic-string.h"
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 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.
jsonrpc_recv_wait(struct jsonrpc *rpc)
{
if (rpc->status || rpc->received || !byteq_is_empty(&rpc->input)) {
- poll_immediate_wake();
+ (poll_immediate_wake)(rpc->name);
} else {
stream_recv_wait(rpc->stream);
}
/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 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.
OPT_CHECK_LEAKS, \
OPT_LEAK_LIMIT
#define LEAK_CHECKER_LONG_OPTIONS \
- {"check-leaks", required_argument, 0, OPT_CHECK_LEAKS}, \
- {"leak-limit", required_argument, 0, OPT_LEAK_LIMIT}
+ {"check-leaks", required_argument, NULL, OPT_CHECK_LEAKS}, \
+ {"leak-limit", required_argument, NULL, OPT_LEAK_LIMIT}
#define LEAK_CHECKER_OPTION_HANDLERS \
case OPT_CHECK_LEAKS: \
leak_checker_start(optarg); \
- /* 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.
}
} while (error == EINTR && (timeout == INT_MAX || elapsed < timeout));
- if (!error) {
- if (elapsed) {
- VLOG_WARN("%s: waited %lld ms for lock file",
- lock_name, elapsed);
- }
- } else if (error == EINTR) {
+ if (error == EINTR) {
COVERAGE_INC(lockfile_timeout);
VLOG_WARN("%s: giving up on lock file after %lld ms",
lock_name, elapsed);
error = ETIMEDOUT;
- } else {
+ } else if (error) {
COVERAGE_INC(lockfile_error);
if (error == EACCES) {
error = EAGAIN;
/* Sockets used for ioctl operations. */
static int af_inet_sock = -1; /* AF_INET, SOCK_DGRAM. */
-static int af_packet_sock = -1; /* AF_PACKET, SOCK_RAW. */
/* A Netlink routing socket that is not subscribed to any multicast groups. */
static struct nl_sock *rtnl_sock;
const uint8_t[ETH_ADDR_LEN]);
static int get_stats_via_netlink(int ifindex, struct netdev_stats *stats);
static int get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats);
+static int af_packet_sock(void);
static bool
is_netdev_linux_class(const struct netdev_class *netdev_class)
status = af_inet_sock >= 0 ? 0 : errno;
if (status) {
VLOG_ERR("failed to create inet socket: %s", strerror(status));
- } else {
- /* Create AF_PACKET socket. */
- af_packet_sock = socket(AF_PACKET, SOCK_RAW, 0);
- status = af_packet_sock >= 0 ? 0 : errno;
- if (status) {
- VLOG_ERR("failed to create packet socket: %s",
- strerror(status));
- }
- set_nonblocking(af_packet_sock);
}
/* Create rtnetlink socket. */
protocol = (ethertype == NETDEV_ETH_TYPE_ANY ? ETH_P_ALL
: ethertype == NETDEV_ETH_TYPE_802_2 ? ETH_P_802_2
: ethertype);
- netdev->fd = socket(PF_PACKET, SOCK_RAW, htons(protocol));
+ netdev->fd = socket(PF_PACKET, SOCK_RAW,
+ (OVS_FORCE int) htons(protocol));
if (netdev->fd < 0) {
error = errno;
goto error;
struct iovec iov;
int ifindex;
int error;
+ int sock;
+
+ sock = af_packet_sock();
+ if (sock < 0) {
+ return sock;
+ }
error = get_ifindex(netdev_, &ifindex);
if (error) {
msg.msg_controllen = 0;
msg.msg_flags = 0;
- retval = sendmsg(af_packet_sock, &msg, 0);
+ retval = sendmsg(sock, &msg, 0);
} else {
/* Use the netdev's own fd to send to this device. This is
* essential for tap devices, because packets sent to a tap device
}
return error;
}
+
+/* Returns an AF_PACKET raw socket or a negative errno value. */
+static int
+af_packet_sock(void)
+{
+ static int sock = INT_MIN;
+
+ if (sock == INT_MIN) {
+ sock = socket(AF_PACKET, SOCK_RAW, 0);
+ if (sock >= 0) {
+ set_nonblocking(sock);
+ } else {
+ sock = -errno;
+ VLOG_ERR("failed to create packet socket: %s", strerror(errno));
+ }
+ }
+
+ return sock;
+}
netdev_vport_get_tnl_iface(const struct netdev *netdev)
{
struct nlattr *a[ODP_TUNNEL_ATTR_MAX + 1];
- uint32_t route;
+ ovs_be32 route;
struct netdev_dev_vport *ndv;
static char name[IFNAMSIZ];
}
}
+/* Clears all notifications from 'monitor'. May be called instead of
+ * netdev_monitor_poll() by clients which don't care specifically which netdevs
+ * have changed. */
+void
+netdev_monitor_flush(struct netdev_monitor *monitor)
+{
+ sset_clear(&monitor->changed_netdevs);
+}
+
/* Registers with the poll loop to wake up from the next call to poll_block()
* when netdev_monitor_poll(monitor) would indicate that a device has
* changed. */
int netdev_monitor_add(struct netdev_monitor *, struct netdev *);
void netdev_monitor_remove(struct netdev_monitor *, struct netdev *);
int netdev_monitor_poll(struct netdev_monitor *, char **devnamep);
+void netdev_monitor_flush(struct netdev_monitor *);
void netdev_monitor_poll_wait(const struct netdev_monitor *);
#ifdef __cplusplus
static void
nxm_put_eth_dst(struct ofpbuf *b,
- uint32_t wc, const uint8_t value[ETH_ADDR_LEN])
+ flow_wildcards_t wc, const uint8_t value[ETH_ADDR_LEN])
{
switch (wc & (FWW_DL_DST | FWW_ETH_MCAST)) {
case FWW_DL_DST | FWW_ETH_MCAST:
data_len = len - offsetof(struct ofp_packet_in, data);
ds_put_format(string, " data_len=%zu", data_len);
- if (htonl(op->buffer_id) == UINT32_MAX) {
+ if (op->buffer_id == htonl(UINT32_MAX)) {
ds_put_format(string, " (unbuffered)");
if (ntohs(op->total_len) != data_len)
ds_put_format(string, " (***total_len != data_len***)");
VLOG_DEFINE_THIS_MODULE(ofp_util);
+static ovs_be32 normalize_wildcards(const struct ofp_match *);
+
/* Rate limit for OpenFlow message parse errors. These always indicate a bug
* in the peer and so there's not much point in showing a lot of them. */
static struct vlog_rate_limit bad_ofmsg_rl = VLOG_RATE_LIMIT_INIT(1, 5);
/* WC_INVARIANTS is the invariant bits (as defined on WC_INVARIANT_LIST) all
* OR'd together. */
-enum {
- WC_INVARIANTS = 0
+static const flow_wildcards_t WC_INVARIANTS = 0
#define WC_INVARIANT_BIT(NAME) | FWW_##NAME
WC_INVARIANT_LIST
#undef WC_INVARIANT_BIT
-};
+;
/* Converts the ofp_match in 'match' into a cls_rule in 'rule', with the given
* 'priority'. */
unsigned int priority, struct cls_rule *rule)
{
struct flow_wildcards *wc = &rule->wc;
- unsigned int ofpfw;
+ uint32_t ofpfw;
ovs_be16 vid, pcp;
/* Initialize rule->priority. */
/* Initialize most of rule->wc. */
flow_wildcards_init_catchall(wc);
- wc->wildcards = ofpfw & WC_INVARIANTS;
+ wc->wildcards = (OVS_FORCE flow_wildcards_t) ofpfw & WC_INVARIANTS;
/* Wildcard fields that aren't defined by ofp_match or tun_id. */
wc->wildcards |= (FWW_ARP_SHA | FWW_ARP_THA | FWW_ND_TARGET);
ofputil_cls_rule_to_match(const struct cls_rule *rule, struct ofp_match *match)
{
const struct flow_wildcards *wc = &rule->wc;
- unsigned int ofpfw;
+ uint32_t ofpfw;
/* Figure out most OpenFlow wildcards. */
- ofpfw = wc->wildcards & WC_INVARIANTS;
+ ofpfw = (OVS_FORCE uint32_t) (wc->wildcards & WC_INVARIANTS);
ofpfw |= ofputil_netmask_to_wcbits(wc->nw_src_mask) << OFPFW_NW_SRC_SHIFT;
ofpfw |= ofputil_netmask_to_wcbits(wc->nw_dst_mask) << OFPFW_NW_DST_SHIFT;
if (wc->wildcards & FWW_NW_TOS) {
ofputil_decode_msg_type(oh, &type);
if (ofputil_msg_type_code(type) == OFPUTIL_OFPT_FLOW_MOD) {
/* Standard OpenFlow flow_mod. */
- struct ofp_match match, orig_match;
const struct ofp_flow_mod *ofm;
+ uint16_t priority;
+ ovs_be32 wc;
int error;
/* Dissect the message. */
return error;
}
+ /* Set priority based on original wildcards. Normally we'd allow
+ * ofputil_cls_rule_from_match() to do this for us, but
+ * normalize_wildcards() can put wildcards where the original flow
+ * didn't have them. */
+ priority = ntohs(ofm->priority);
+ if (!(ofm->match.wildcards & htonl(OFPFW_ALL))) {
+ priority = UINT16_MAX;
+ }
+
/* Normalize ofm->match. If normalization actually changes anything,
* then log the differences. */
- match = ofm->match;
- match.pad1[0] = match.pad2[0] = 0;
- orig_match = match;
- normalize_match(&match);
- if (memcmp(&match, &orig_match, sizeof orig_match)) {
+ wc = normalize_wildcards(&ofm->match);
+ if (wc == ofm->match.wildcards) {
+ ofputil_cls_rule_from_match(&ofm->match, priority, &fm->cr);
+ } else {
+ struct ofp_match match = ofm->match;
+ match.wildcards = wc;
+ ofputil_cls_rule_from_match(&match, priority, &fm->cr);
+
if (!VLOG_DROP_INFO(&bad_ofmsg_rl)) {
- char *old = ofp_match_to_literal_string(&orig_match);
- char *new = ofp_match_to_literal_string(&match);
+ char *pre = ofp_match_to_string(&ofm->match, 1);
+ char *post = ofp_match_to_string(&match, 1);
VLOG_INFO("normalization changed ofp_match, details:");
- VLOG_INFO(" pre: %s", old);
- VLOG_INFO("post: %s", new);
- free(old);
- free(new);
+ VLOG_INFO(" pre: %s", pre);
+ VLOG_INFO("post: %s", post);
+ free(pre);
+ free(post);
}
}
/* Translate the message. */
- ofputil_cls_rule_from_match(&match, ntohs(ofm->priority), &fm->cr);
fm->cookie = ofm->cookie;
command = ntohs(ofm->command);
fm->idle_timeout = ntohs(ofm->idle_timeout);
}
}
-void
-normalize_match(struct ofp_match *m)
+static ovs_be32
+normalize_wildcards(const struct ofp_match *m)
{
- enum { OFPFW_NW = (OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_NW_PROTO
+ enum { OFPFW_NW = (OFPFW_NW_SRC_ALL | OFPFW_NW_DST_ALL | OFPFW_NW_PROTO
| OFPFW_NW_TOS) };
enum { OFPFW_TP = OFPFW_TP_SRC | OFPFW_TP_DST };
- uint32_t wc;
-
- wc = ntohl(m->wildcards) & OFPFW_ALL;
- if (wc & OFPFW_DL_TYPE) {
- m->dl_type = 0;
+ ovs_be32 wc;
- /* Can't sensibly match on network or transport headers if the
- * data link type is unknown. */
- wc |= OFPFW_NW | OFPFW_TP;
- m->nw_src = m->nw_dst = m->nw_proto = m->nw_tos = 0;
- m->tp_src = m->tp_dst = 0;
+ wc = m->wildcards;
+ if (wc & htonl(OFPFW_DL_TYPE)) {
+ wc |= htonl(OFPFW_NW | OFPFW_TP);
} else if (m->dl_type == htons(ETH_TYPE_IP)) {
- if (wc & OFPFW_NW_PROTO) {
- m->nw_proto = 0;
-
- /* Can't sensibly match on transport headers if the network
- * protocol is unknown. */
- wc |= OFPFW_TP;
- m->tp_src = m->tp_dst = 0;
- } else if (m->nw_proto == IPPROTO_TCP ||
- m->nw_proto == IPPROTO_UDP ||
- m->nw_proto == IPPROTO_ICMP) {
- if (wc & OFPFW_TP_SRC) {
- m->tp_src = 0;
- }
- if (wc & OFPFW_TP_DST) {
- m->tp_dst = 0;
- }
- } else {
- /* Transport layer fields will always be extracted as zeros, so we
- * can do an exact-match on those values. */
- wc &= ~OFPFW_TP;
- m->tp_src = m->tp_dst = 0;
- }
- if (wc & OFPFW_NW_SRC_MASK) {
- m->nw_src &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_SRC_SHIFT);
- }
- if (wc & OFPFW_NW_DST_MASK) {
- m->nw_dst &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_DST_SHIFT);
- }
- if (wc & OFPFW_NW_TOS) {
- m->nw_tos = 0;
- } else {
- m->nw_tos &= IP_DSCP_MASK;
+ if (wc & htonl(OFPFW_NW_PROTO) || (m->nw_proto != IPPROTO_TCP &&
+ m->nw_proto != IPPROTO_UDP &&
+ m->nw_proto != IPPROTO_ICMP)) {
+ wc |= htonl(OFPFW_TP);
}
} else if (m->dl_type == htons(ETH_TYPE_ARP)) {
- if (wc & OFPFW_NW_PROTO) {
- m->nw_proto = 0;
- }
- if (wc & OFPFW_NW_SRC_MASK) {
- m->nw_src &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_SRC_SHIFT);
- }
- if (wc & OFPFW_NW_DST_MASK) {
- m->nw_dst &= ofputil_wcbits_to_netmask(wc >> OFPFW_NW_DST_SHIFT);
- }
- m->tp_src = m->tp_dst = m->nw_tos = 0;
- } else if (m->dl_type == htons(ETH_TYPE_IPV6)) {
- /* Don't normalize IPv6 traffic, since OpenFlow doesn't have a
- * way to express it. */
+ wc |= htonl(OFPFW_TP);
} else {
- /* Network and transport layer fields will always be extracted as
- * zeros, so we can do an exact-match on those values. */
- wc &= ~(OFPFW_NW | OFPFW_TP);
- m->nw_proto = m->nw_src = m->nw_dst = m->nw_tos = 0;
- m->tp_src = m->tp_dst = 0;
+ wc |= htonl(OFPFW_NW | OFPFW_TP);
}
- if (wc & OFPFW_DL_SRC) {
- memset(m->dl_src, 0, sizeof m->dl_src);
- }
- if (wc & OFPFW_DL_DST) {
- memset(m->dl_dst, 0, sizeof m->dl_dst);
- }
- m->wildcards = htonl(wc);
-}
-
-/* Returns a string that describes 'match' in a very literal way, without
- * interpreting its contents except in a very basic fashion. The returned
- * string is intended to be fixed-length, so that it is easy to see differences
- * between two such strings if one is put above another. This is useful for
- * describing changes made by normalize_match().
- *
- * The caller must free the returned string (with free()). */
-char *
-ofp_match_to_literal_string(const struct ofp_match *match)
-{
- return xasprintf("wildcards=%#10"PRIx32" "
- " in_port=%5"PRId16" "
- " dl_src="ETH_ADDR_FMT" "
- " dl_dst="ETH_ADDR_FMT" "
- " dl_vlan=%5"PRId16" "
- " dl_vlan_pcp=%3"PRId8" "
- " dl_type=%#6"PRIx16" "
- " nw_tos=%#4"PRIx8" "
- " nw_proto=%#4"PRIx16" "
- " nw_src=%#10"PRIx32" "
- " nw_dst=%#10"PRIx32" "
- " tp_src=%5"PRId16" "
- " tp_dst=%5"PRId16,
- ntohl(match->wildcards),
- ntohs(match->in_port),
- ETH_ADDR_ARGS(match->dl_src),
- ETH_ADDR_ARGS(match->dl_dst),
- ntohs(match->dl_vlan),
- match->dl_vlan_pcp,
- ntohs(match->dl_type),
- match->nw_tos,
- match->nw_proto,
- ntohl(match->nw_src),
- ntohl(match->nw_dst),
- ntohs(match->tp_src),
- ntohs(match->tp_dst));
+ return wc;
}
static uint32_t
void ofputil_cls_rule_from_match(const struct ofp_match *,
unsigned int priority, struct cls_rule *);
void ofputil_cls_rule_to_match(const struct cls_rule *, struct ofp_match *);
-void normalize_match(struct ofp_match *);
-char *ofp_match_to_literal_string(const struct ofp_match *match);
/* dl_type translation between OpenFlow and 'struct flow' format. */
ovs_be16 ofputil_dl_type_to_openflow(ovs_be16 flow_dl_type);
#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 {
/*
- * 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 <poll.h>
#include <stdlib.h>
#include <string.h>
-#include "backtrace.h"
#include "coverage.h"
#include "dynamic-string.h"
#include "fatal-signal.h"
#include "list.h"
+#include "socket-util.h"
#include "timeval.h"
#include "vlog.h"
+#undef poll_fd_wait
+#undef poll_timer_wait
+#undef poll_timer_wait_until
+#undef poll_immediate_wake
+
VLOG_DEFINE_THIS_MODULE(poll_loop);
COVERAGE_DEFINE(poll_fd_wait);
struct list node; /* Element in global waiters list. */
int fd; /* File descriptor. */
short int events; /* Events to wait for (POLLIN, POLLOUT). */
- struct backtrace *backtrace; /* Optionally, event that created waiter. */
+ const char *where; /* Where the waiter was created. */
/* Set only when poll_block() is called. */
struct pollfd *pollfd; /* Pointer to element of the pollfds array. */
* wait forever. */
static int timeout = -1;
-/* Backtrace of 'timeout''s registration, if debugging is enabled. */
-static struct backtrace timeout_backtrace;
+/* Location where waiter created. */
+static const char *timeout_where;
-static struct poll_waiter *new_waiter(int fd, short int events);
+static struct poll_waiter *new_waiter(int fd, short int events,
+ const char *where);
/* Registers 'fd' as waiting for the specified 'events' (which should be POLLIN
* or POLLOUT or POLLIN | POLLOUT). The following call to poll_block() will
*
* The event registration is one-shot: only the following call to poll_block()
* is affected. The event will need to be re-registered after poll_block() is
- * called if it is to persist. */
+ * called if it is to persist.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
struct poll_waiter *
-poll_fd_wait(int fd, short int events)
+poll_fd_wait(int fd, short int events, const char *where)
{
COVERAGE_INC(poll_fd_wait);
- return new_waiter(fd, events);
+ return new_waiter(fd, events, where);
}
/* The caller must ensure that 'msec' is not negative. */
static void
-poll_timer_wait__(int msec)
+poll_timer_wait__(int msec, const char *where)
{
if (timeout < 0 || msec < timeout) {
timeout = msec;
- if (VLOG_IS_DBG_ENABLED()) {
- backtrace_capture(&timeout_backtrace);
- }
+ timeout_where = where;
}
}
*
* The timer registration is one-shot: only the following call to poll_block()
* is affected. The timer will need to be re-registered after poll_block() is
- * called if it is to persist. */
+ * called if it is to persist.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
void
-poll_timer_wait(long long int msec)
+poll_timer_wait(long long int msec, const char *where)
{
- poll_timer_wait__(msec < 0 ? 0
- : msec > INT_MAX ? INT_MAX
- : msec);
+ poll_timer_wait__((msec < 0 ? 0
+ : msec > INT_MAX ? INT_MAX
+ : msec),
+ where);
}
/* Causes the following call to poll_block() to wake up when the current time,
*
* The timer registration is one-shot: only the following call to poll_block()
* is affected. The timer will need to be re-registered after poll_block() is
- * called if it is to persist. */
+ * called if it is to persist.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
void
-poll_timer_wait_until(long long int msec)
+poll_timer_wait_until(long long int msec, const char *where)
{
long long int now = time_msec();
- poll_timer_wait__(msec <= now ? 0
- : msec < now + INT_MAX ? msec - now
- : INT_MAX);
+ poll_timer_wait__((msec <= now ? 0
+ : msec < now + INT_MAX ? msec - now
+ : INT_MAX),
+ where);
}
/* Causes the following call to poll_block() to wake up immediately, without
- * blocking. */
+ * blocking.
+ *
+ * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h
+ * for more information. */
void
-poll_immediate_wake(void)
+poll_immediate_wake(const char *where)
{
- poll_timer_wait(0);
+ poll_timer_wait(0, where);
}
static void PRINTF_FORMAT(2, 3)
-log_wakeup(const struct backtrace *backtrace, const char *format, ...)
+log_wakeup(const char *where, const char *format, ...)
{
struct ds ds;
va_list args;
ds_put_format_valist(&ds, format, args);
va_end(args);
- if (backtrace) {
- int i;
-
- ds_put_char(&ds, ':');
- for (i = 0; i < backtrace->n_frames; i++) {
- ds_put_format(&ds, " 0x%"PRIxPTR, backtrace->frames[i]);
- }
+ if (where) {
+ ds_put_format(&ds, " at %s", where);
}
+
VLOG_DBG("%s", ds_cstr(&ds));
ds_destroy(&ds);
}
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_ERR_RL(&rl, "poll: %s", strerror(-retval));
} else if (!retval && VLOG_IS_DBG_ENABLED()) {
- log_wakeup(&timeout_backtrace, "%d-ms timeout", timeout);
+ log_wakeup(timeout_where, "%d-ms timeout", timeout);
}
LIST_FOR_EACH_SAFE (pw, next, node, &waiters) {
if (pw->pollfd->revents && VLOG_IS_DBG_ENABLED()) {
- log_wakeup(pw->backtrace, "%s%s%s%s%s on fd %d",
+ char *description = describe_fd(pw->fd);
+ log_wakeup(pw->where, "%s%s%s%s%s on fd %d (%s)",
pw->pollfd->revents & POLLIN ? "[POLLIN]" : "",
pw->pollfd->revents & POLLOUT ? "[POLLOUT]" : "",
pw->pollfd->revents & POLLERR ? "[POLLERR]" : "",
pw->pollfd->revents & POLLHUP ? "[POLLHUP]" : "",
pw->pollfd->revents & POLLNVAL ? "[POLLNVAL]" : "",
- pw->fd);
+ pw->fd, description);
+ free(description);
}
poll_cancel(pw);
}
timeout = -1;
- timeout_backtrace.n_frames = 0;
+ timeout_where = NULL;
/* Handle any pending signals before doing anything else. */
fatal_signal_run();
{
if (pw) {
list_remove(&pw->node);
- free(pw->backtrace);
free(pw);
n_waiters--;
}
\f
/* Creates and returns a new poll_waiter for 'fd' and 'events'. */
static struct poll_waiter *
-new_waiter(int fd, short int events)
+new_waiter(int fd, short int events, const char *where)
{
struct poll_waiter *waiter = xzalloc(sizeof *waiter);
assert(fd >= 0);
waiter->fd = fd;
waiter->events = events;
- if (VLOG_IS_DBG_ENABLED()) {
- waiter->backtrace = xmalloc(sizeof *waiter->backtrace);
- backtrace_capture(waiter->backtrace);
- }
+ waiter->where = where;
list_push_back(&waiters, &waiter->node);
n_waiters++;
return waiter;
/*
- * 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.
#define POLL_LOOP_H 1
#include <poll.h>
+#include "util.h"
#ifdef __cplusplus
extern "C" {
struct poll_waiter;
-/* Schedule events to wake up the following poll_block(). */
-struct poll_waiter *poll_fd_wait(int fd, short int events);
-void poll_timer_wait(long long int msec);
-void poll_timer_wait_until(long long int msec);
-void poll_immediate_wake(void);
+/* Schedule events to wake up the following poll_block().
+ *
+ * The poll_loop logs the 'where' argument to each function at "debug" level
+ * when an event causes a wakeup. Ordinarily, it is automatically filled in
+ * with the location in the source of the call, and caller should therefore
+ * omit it. But, if the function you are implementing is very generic, so that
+ * its location in the source would not be very helpful for debugging, you can
+ * avoid the macro expansion and pass a different argument, e.g.:
+ * (poll_fd_wait)(fd, events, where);
+ * See timer_wait() for an example.
+ */
+struct poll_waiter *poll_fd_wait(int fd, short int events, const char *where);
+#define poll_fd_wait(fd, events) poll_fd_wait(fd, events, SOURCE_LOCATOR)
+
+void poll_timer_wait(long long int msec, const char *where);
+#define poll_timer_wait(msec) poll_timer_wait(msec, SOURCE_LOCATOR)
+
+void poll_timer_wait_until(long long int msec, const char *where);
+#define poll_timer_wait_until(msec) poll_timer_wait_until(msec, SOURCE_LOCATOR)
+
+void poll_immediate_wake(const char *where);
+#define poll_immediate_wake() poll_immediate_wake(SOURCE_LOCATOR)
/* Wait until an event occurs. */
void poll_block(void);
*
* We don't cache the local port, because that changes from one connection
* attempt to the next. */
- uint32_t local_ip, remote_ip;
- uint16_t remote_port;
+ ovs_be32 local_ip, remote_ip;
+ ovs_be16 remote_port;
/* Messages sent or received are copied to the monitor connections. */
#define MAX_MONITORS 8
struct rtnetlink *rtn;
rtn = xzalloc(sizeof *rtn);
- rtn->notify_sock = 0;
+ rtn->notify_sock = NULL;
rtn->multicast_group = multicast_group;
rtn->parse = parse;
rtn->change = change;
/* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
/* http://www.inmon.com/technology/sflowlicense.txt */
+#ifndef __CHECKER__ /* Don't run sparse on anything in this file. */
+
#include <assert.h>
#include "sflow_api.h"
sfl_agent_error(receiver->agent, "receiver", msg);
resetSampleCollector(receiver);
}
+
+#endif /* !__CHECKER__ */
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
+#include <net/if.h>
#include <netdb.h>
#include <poll.h>
#include <stddef.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
+#include "dynamic-string.h"
#include "fatal-signal.h"
+#include "packets.h"
#include "util.h"
#include "vlog.h"
+#if AF_PACKET && __linux__
+#include <linux/if_packet.h>
+#endif
+#ifdef HAVE_NETLINK
+#include "netlink-protocol.h"
+#include "netlink-socket.h"
+#endif
VLOG_DEFINE_THIS_MODULE(socket_util);
VLOG_FATAL("failed to create pipe (%s)", strerror(errno));
}
}
+
+static int
+getsockopt_int(int fd, int level, int optname, int *valuep)
+{
+ socklen_t len = sizeof *valuep;
+
+ return (getsockopt(fd, level, optname, valuep, &len) ? errno
+ : len == sizeof *valuep ? 0
+ : EINVAL);
+}
+
+static void
+describe_sockaddr(struct ds *string, int fd,
+ int (*getaddr)(int, struct sockaddr *, socklen_t *))
+{
+ struct sockaddr_storage ss;
+ socklen_t len = sizeof ss;
+
+ if (!getaddr(fd, (struct sockaddr *) &ss, &len)) {
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in sin;
+
+ memcpy(&sin, &ss, sizeof sin);
+ ds_put_format(string, IP_FMT":%"PRIu16,
+ IP_ARGS(&sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ } else if (ss.ss_family == AF_UNIX) {
+ struct sockaddr_un sun;
+ const char *null;
+ size_t maxlen;
+
+ memcpy(&sun, &ss, sizeof sun);
+ maxlen = len - offsetof(struct sockaddr_un, sun_path);
+ null = memchr(sun.sun_path, '\0', maxlen);
+ ds_put_buffer(string, sun.sun_path,
+ null ? null - sun.sun_path : maxlen);
+ }
+#ifdef HAVE_NETLINK
+ else if (ss.ss_family == AF_NETLINK) {
+ int protocol;
+
+/* SO_PROTOCOL was introduced in 2.6.32. Support it regardless of the version
+ * of the Linux kernel headers in use at build time. */
+#ifndef SO_PROTOCOL
+#define SO_PROTOCOL 38
+#endif
+
+ if (!getsockopt_int(fd, SOL_SOCKET, SO_PROTOCOL, &protocol)) {
+ switch (protocol) {
+ case NETLINK_ROUTE:
+ ds_put_cstr(string, "NETLINK_ROUTE");
+ break;
+
+ case NETLINK_GENERIC:
+ ds_put_cstr(string, "NETLINK_GENERIC");
+ break;
+
+ default:
+ ds_put_format(string, "AF_NETLINK family %d", protocol);
+ break;
+ }
+ } else {
+ ds_put_cstr(string, "AF_NETLINK");
+ }
+ }
+#endif
+#if AF_PACKET && __linux__
+ else if (ss.ss_family == AF_PACKET) {
+ struct sockaddr_ll sll;
+
+ memcpy(&sll, &ss, sizeof sll);
+ ds_put_cstr(string, "AF_PACKET");
+ if (sll.sll_ifindex) {
+ char name[IFNAMSIZ];
+
+ if (if_indextoname(sll.sll_ifindex, name)) {
+ ds_put_format(string, "(%s)", name);
+ } else {
+ ds_put_format(string, "(ifindex=%d)", sll.sll_ifindex);
+ }
+ }
+ if (sll.sll_protocol) {
+ ds_put_format(string, "(protocol=0x%"PRIu16")",
+ ntohs(sll.sll_protocol));
+ }
+ }
+#endif
+ else if (ss.ss_family == AF_UNSPEC) {
+ ds_put_cstr(string, "AF_UNSPEC");
+ } else {
+ ds_put_format(string, "AF_%d", (int) ss.ss_family);
+ }
+ }
+}
+
+
+#ifdef __linux__
+static void
+put_fd_filename(struct ds *string, int fd)
+{
+ char buf[1024];
+ char *linkname;
+ int n;
+
+ linkname = xasprintf("/proc/self/fd/%d", fd);
+ n = readlink(linkname, buf, sizeof buf);
+ if (n > 0) {
+ ds_put_char(string, ' ');
+ ds_put_buffer(string, buf, n);
+ if (n > sizeof buf) {
+ ds_put_cstr(string, "...");
+ }
+ }
+ free(linkname);
+}
+#endif
+
+/* Returns a malloc()'d string describing 'fd', for use in logging. */
+char *
+describe_fd(int fd)
+{
+ struct ds string;
+ struct stat s;
+
+ ds_init(&string);
+ if (fstat(fd, &s)) {
+ ds_put_format(&string, "fstat failed (%s)", strerror(errno));
+ } else if (S_ISSOCK(s.st_mode)) {
+ describe_sockaddr(&string, fd, getsockname);
+ ds_put_cstr(&string, "<->");
+ describe_sockaddr(&string, fd, getpeername);
+ } else {
+ ds_put_cstr(&string, (isatty(fd) ? "tty"
+ : S_ISDIR(s.st_mode) ? "directory"
+ : S_ISCHR(s.st_mode) ? "character device"
+ : S_ISBLK(s.st_mode) ? "block device"
+ : S_ISREG(s.st_mode) ? "file"
+ : S_ISFIFO(s.st_mode) ? "FIFO"
+ : S_ISLNK(s.st_mode) ? "symbolic link"
+ : "unknown"));
+#ifdef __linux__
+ put_fd_filename(&string, fd);
+#endif
+ }
+ return ds_steal_cstr(&string);
+}
void xpipe(int fds[2]);
+char *describe_fd(int fd);
+
#endif /* socket-util.h */
int new_fd;
int error;
- new_fd = accept(pssl->fd, &sin, &sin_len);
+ new_fd = accept(pssl->fd, (struct sockaddr *) &sin, &sin_len);
if (new_fd < 0) {
error = errno;
if (error != EAGAIN) {
const char *certificate_file);
#define STREAM_SSL_LONG_OPTIONS \
- {"private-key", required_argument, 0, 'p'}, \
- {"certificate", required_argument, 0, 'c'}, \
- {"ca-cert", required_argument, 0, 'C'}
+ {"private-key", required_argument, NULL, 'p'}, \
+ {"certificate", required_argument, NULL, 'c'}, \
+ {"ca-cert", required_argument, NULL, 'C'}
#define STREAM_SSL_OPTION_HANDLERS \
case 'p': \
/*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 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.
#if USE_LINKER_SECTIONS
#define STRESS_OPTION(NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT) \
STRESS_OPTION__(NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT); \
+ extern struct stress_option *stress_option_ptr_##NAME; \
struct stress_option *stress_option_ptr_##NAME \
__attribute__((section("stress_options"))) = &stress_##NAME
#else
/* Implementation details. */
#define STRESS_OPTION__(NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT) \
+ extern struct stress_option stress_##NAME; \
struct stress_option stress_##NAME = \
{ #NAME, DESCRIPTION, RECOMMENDED, MIN, MAX, DEFAULT, \
DEFAULT ? DEFAULT : 0, /* period */ \
OPT_PRETTY, \
OPT_BARE
-#define TABLE_LONG_OPTIONS \
- {"format", required_argument, 0, 'f'}, \
- {"data", required_argument, 0, 'd'}, \
- {"no-headings", no_argument, 0, OPT_NO_HEADINGS}, \
- {"pretty", no_argument, 0, OPT_PRETTY}, \
- {"bare", no_argument, 0, OPT_BARE}
+#define TABLE_LONG_OPTIONS \
+ {"format", required_argument, NULL, 'f'}, \
+ {"data", required_argument, NULL, 'd'}, \
+ {"no-headings", no_argument, NULL, OPT_NO_HEADINGS}, \
+ {"pretty", no_argument, NULL, OPT_PRETTY}, \
+ {"bare", no_argument, NULL, OPT_BARE}
#define TABLE_OPTION_HANDLERS(STYLE) \
case 'f': \
/* Causes poll_block() to wake when 'timer' expires. */
void
-timer_wait(const struct timer *timer)
+(timer_wait)(const struct timer *timer, const char *where)
{
if (timer->t < LLONG_MAX) {
- poll_timer_wait_until(timer->t);
- }
-}
-
-/* Returns the time at which 'timer' was set with 'duration'. Infinite timers
- * were enabled at time LLONG_MAX. Manually expired timers were enabled at
- * LLONG_MIN. */
-long long int
-timer_enabled_at(const struct timer *timer, long long int duration)
-{
- switch (timer->t) {
- case LLONG_MAX: return LLONG_MAX;
- case LLONG_MIN: return LLONG_MIN;
- default: return timer->t - duration;
+ (poll_timer_wait_until)(timer->t, where);
}
}
#include <stdbool.h>
#include "timeval.h"
+#include "util.h"
struct timer {
long long int t;
};
long long int timer_msecs_until_expired(const struct timer *);
-long long int timer_enabled_at(const struct timer *, long long int duration);
-void timer_wait(const struct timer *);
+void timer_wait(const struct timer *, const char *where);
+#define timer_wait(timer) timer_wait(timer, SOURCE_LOCATOR)
/* Causes 'timer' to expire when 'duration' milliseconds have passed.
*
x->lo = value;
}
+#ifndef __CHECKER__
/* Returns the value of 'x'. */
static inline ovs_be64
get_32aligned_be64(const ovs_32aligned_be64 *x)
x->lo = value >> 32;
#endif
}
+#else /* __CHECKER__ */
+/* Making sparse happy with these functions also makes them unreadable, so
+ * don't bother to show it their implementations. */
+ovs_be64 get_32aligned_be64(const ovs_32aligned_be64 *);
+void put_32aligned_be64(ovs_32aligned_be64 *, ovs_be64);
+#endif
#endif /* unaligned.h */
#endif
#endif
-#ifndef __cplusplus
+#ifdef __CHECKER__
+#define BUILD_ASSERT(EXPR) ((void) 0)
+#define BUILD_ASSERT_DECL(EXPR) extern int (*build_assert(void))[1]
+#elif !defined(__cplusplus)
/* Build-time assertion building block. */
#define BUILD_ASSERT__(EXPR) \
sizeof(struct { unsigned int build_assert_failed : (EXPR) ? 1 : -1; })
#define NOT_REACHED() abort()
+/* Expands to a string that looks like "<file>:<line>", e.g. "tmp.c:10".
+ *
+ * See http://c-faq.com/ansi/stringize.html for an explanation of STRINGIZE and
+ * STRINGIZE2. */
+#define SOURCE_LOCATOR __FILE__ ":" STRINGIZE(__LINE__)
+#define STRINGIZE(ARG) STRINGIZE2(ARG)
+#define STRINGIZE2(ARG) #ARG
+
/* Given a pointer-typed lvalue OBJECT, expands to a pointer type that may be
* assigned to OBJECT. */
#ifdef __GNUC__
#if USE_LINKER_SECTIONS
#define VLOG_DEFINE_MODULE(MODULE) \
VLOG_DEFINE_MODULE__(MODULE) \
+ extern struct vlog_module *vlog_module_ptr_##MODULE; \
struct vlog_module *vlog_module_ptr_##MODULE \
__attribute__((section("vlog_modules"))) = &VLM_##MODULE
#else
/* Command line processing. */
#define VLOG_OPTION_ENUMS OPT_LOG_FILE
#define VLOG_LONG_OPTIONS \
- {"verbose", optional_argument, 0, 'v'}, \
- {"log-file", optional_argument, 0, OPT_LOG_FILE}
+ {"verbose", optional_argument, NULL, 'v'}, \
+ {"log-file", optional_argument, NULL, OPT_LOG_FILE}
#define VLOG_OPTION_HANDLERS \
case 'v': \
vlog_set_verbosity(optarg); \
} while (0)
#define VLOG_DEFINE_MODULE__(MODULE) \
+ extern struct vlog_module VLM_##MODULE; \
struct vlog_module VLM_##MODULE = \
{ \
#MODULE, /* name */ \
[LOGDIR='${localstatedir}/log/${PACKAGE}'])
AC_SUBST([LOGDIR])])
+dnl Defines HAVE_BACKTRACE if backtrace() is declared in <execinfo.h>
+dnl and exists in libc.
+AC_DEFUN([OVS_CHECK_BACKTRACE],
+ [AC_CHECK_HEADER([execinfo.h], [AC_CHECK_FUNCS([backtrace])])])
+
dnl Checks for __malloc_hook, etc., supported by glibc.
AC_DEFUN([OVS_CHECK_MALLOC_HOOKS],
[AC_CACHE_CHECK(
nf_rec = ofpbuf_put_zeros(&nf->packet, sizeof *nf_rec);
nf_rec->src_addr = expired->flow.nw_src;
nf_rec->dst_addr = expired->flow.nw_dst;
- nf_rec->nexthop = htons(0);
+ nf_rec->nexthop = htonl(0);
if (nf->add_id_to_iface) {
uint16_t iface = (nf->engine_id & 0x7f) << 9;
nf_rec->input = htons(iface | (expired->flow.in_port & 0x1ff));
static int expire(struct ofproto_dpif *);
/* Utilities. */
-static int send_packet(struct ofproto_dpif *,
- uint32_t odp_port, uint16_t vlan_tci,
+static int send_packet(struct ofproto_dpif *, uint32_t odp_port,
const struct ofpbuf *packet);
/* Global variables. */
ETH_TYPE_CFM, sizeof *ccm);
cfm_compose_ccm(ofport->cfm, ccm);
send_packet(ofproto_dpif_cast(ofport->up.ofproto),
- ofport->odp_port, 0, &packet);
+ ofport->odp_port, &packet);
ofpbuf_uninit(&packet);
}
}
/* Check with in-band control to see if this packet should be sent
* to the local port regardless of the flow table. */
if (connmgr_msg_in_hook(ofproto->up.connmgr, &flow, upcall->packet)) {
- send_packet(ofproto, OFPP_LOCAL, 0, upcall->packet);
+ send_packet(ofproto, OFPP_LOCAL, upcall->packet);
}
facet = facet_lookup_valid(ofproto, &flow);
return error;
}
\f
-/* Sends 'packet' out of port 'odp_port' within 'ofproto'. If 'vlan_tci' is
- * zero the packet will not have any 802.1Q hader; if it is nonzero, then the
- * packet will be sent with the VLAN TCI specified by 'vlan_tci & ~VLAN_CFI'.
- *
+/* Sends 'packet' out of port 'odp_port' within 'p'.
* Returns 0 if successful, otherwise a positive errno value. */
static int
-send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port, uint16_t vlan_tci,
+send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port,
const struct ofpbuf *packet)
{
struct ofpbuf odp_actions;
int error;
ofpbuf_init(&odp_actions, 32);
- if (vlan_tci != 0) {
- nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
- ntohs(vlan_tci & ~VLAN_CFI));
- }
nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port);
error = dpif_execute(ofproto->dpif, odp_actions.data, odp_actions.size,
packet);
return false;
success:
- agent_addr->address.ip_v4.addr = in4.s_addr;
+ agent_addr->address.ip_v4.addr = (OVS_FORCE uint32_t) in4.s_addr;
return true;
}
*
* The log message mentions 'msg_type'. */
static int
-reject_slave_controller(struct ofconn *ofconn, const const char *msg_type)
+reject_slave_controller(struct ofconn *ofconn, const char *msg_type)
{
if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
&& ofconn_get_role(ofconn) == NX_ROLE_SLAVE) {
return results;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_commit(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result OVS_UNUSED)
{
}
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_insert(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result)
{
return error;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_select(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result)
{
return true;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_update(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result)
{
return true;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_mutate(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result)
{
return true;
}
-struct ovsdb_error *
+static struct ovsdb_error *
ovsdb_execute_delete(struct ovsdb_execution *x, struct ovsdb_parser *parser,
struct json *result)
{
-/* Copyright (c) 2009, 2010 Nicira Networks
+/* Copyright (c) 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.
struct ovsdb_jsonrpc_session;
/* Message rate-limiting. */
-struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
/* Sessions. */
static struct ovsdb_jsonrpc_session *ovsdb_jsonrpc_session_create(
file->prev_offset = file->offset;
file->offset = data_offset + data_length;
*jsonp = json;
- return 0;
+ return NULL;
error:
file->read_error = ovsdb_error_clone(error);
file->offset += strlen(header) + length;
free(json_string);
- return 0;
+ return NULL;
error:
file->write_error = ovsdb_error_clone(error);
if (fsync(fileno(file->stream))) {
return ovsdb_io_error(errno, "%s: fsync failed", file->name);
}
- return 0;
+ return NULL;
}
/* Returns the current offset into the file backing 'log', in bytes. This
TABLE_OPTION_ENUMS
};
static struct option long_options[] = {
- {"verbose", optional_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
+ {"verbose", optional_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
DAEMON_LONG_OPTIONS,
#ifdef HAVE_OPENSSL
- {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
+ {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
STREAM_SSL_LONG_OPTIONS,
#endif
TABLE_LONG_OPTIONS,
- {0, 0, 0, 0},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
const union ovsdb_atom *atom;
atom = read_column(row, column_name, OVSDB_TYPE_STRING);
- *stringp = atom ? atom->string : 0;
+ *stringp = atom ? atom->string : NULL;
return atom != NULL;
}
DAEMON_OPTION_ENUMS
};
static struct option long_options[] = {
- {"remote", required_argument, 0, OPT_REMOTE},
- {"unixctl", required_argument, 0, OPT_UNIXCTL},
- {"run", required_argument, 0, OPT_RUN},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
+ {"remote", required_argument, NULL, OPT_REMOTE},
+ {"unixctl", required_argument, NULL, OPT_UNIXCTL},
+ {"run", required_argument, NULL, OPT_RUN},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
DAEMON_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
LEAK_CHECKER_LONG_OPTIONS,
- {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
- {"private-key", required_argument, 0, 'p'},
- {"certificate", required_argument, 0, 'c'},
- {"ca-cert", required_argument, 0, 'C'},
- {0, 0, 0, 0},
+ {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
+ {"private-key", required_argument, NULL, 'p'},
+ {"certificate", required_argument, NULL, 'c'},
+ {"ca-cert", required_argument, NULL, 'C'},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
parse_options(int argc, char *argv[])
{
static struct option long_options[] = {
- {"more", no_argument, 0, 'm'},
- {"verbose", optional_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {0, 0, 0, 0},
+ {"more", no_argument, NULL, 'm'},
+ {"verbose", optional_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
}
*schemap = schema;
- return 0;
+ return NULL;
}
struct json *
add_column(ts, column);
}
*tsp = ts;
- return 0;
+ return NULL;
}
/* Returns table schema 'ts' serialized into JSON.
AT_SETUP([autopath basic])
AT_CHECK([ovs-ofctl parse-flow 'actions=autopath(1, NXM_NX_REG0[[]])'], [0],
[OFPT_FLOW_MOD (xid=0x1): ADD actions=autopath(1,NXM_NX_REG0[[]])
-], [ignore])
+])
AT_CHECK([ovs-ofctl parse-flow 'actions=autopath(2, NXM_NX_REG0[[2..30]])'], [0],
[OFPT_FLOW_MOD (xid=0x1): ADD actions=autopath(2,NXM_NX_REG0[[2..30]])
-], [ignore])
+])
AT_CLEANUP
AT_SETUP([autopath action missing argument])
AT_CAPTURE_FILE([expected])
# Start the daemon and wait for the pidfile to get created
# and that its contents are the correct pid.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid& echo $! > expected], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid& echo $! > expected], [0])
OVS_WAIT_UNTIL([test -s pid], [kill `cat expected`])
AT_CHECK(
[pid=`cat pid` && expected=`cat expected` && test "$pid" = "$expected"],
AT_CAPTURE_FILE([parentpid])
AT_CAPTURE_FILE([newpid])
# Start the daemon and wait for the pidfile to get created.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0])
OVS_WAIT_UNTIL([test -s pid], [kill `cat parent`])
# Check that the pidfile names a running process,
# and that the parent process of that process is our child process.
AT_CAPTURE_FILE([parentpid])
AT_CAPTURE_FILE([newpid])
# Start the daemon and wait for the pidfile to get created.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --monitor& echo $! > parent], [0])
OVS_WAIT_UNTIL([test -s pid], [kill `cat parent`])
# Check that the pidfile names a running process,
# and that the parent process of that process is our child process.
# Start the daemon and make sure that the pidfile exists immediately.
# We don't wait for the pidfile to get created because the daemon is
# supposed to do so before the parent exits.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --detach], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/pid --detach], [0])
AT_CHECK([test -s pid])
AT_CHECK([kill -0 `cat pid`])
# Kill the daemon and make sure that the pidfile gets deleted.
# Start the daemon and make sure that the pidfile exists immediately.
# We don't wait for the pidfile to get created because the daemon is
# supposed to do so before the parent exits.
-AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/daemon --detach --monitor], [0], [ignore], [ignore])
+AT_CHECK([$PYTHON $srcdir/test-daemon.py --pidfile-name=$PWD/daemon --detach --monitor], [0])
AT_CHECK([test -s daemon])
# Check that the pidfile names a running process,
# and that the parent process of that process is a running process,
AT_CAPTURE_FILE([expected])
# Start the daemon and wait for the pidfile to get created
# and that its contents are the correct pid.
-AT_CHECK([ovsdb-server --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > expected], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > expected], [0])
OVS_WAIT_UNTIL([test -s pid], [kill `cat expected`])
AT_CHECK(
[pid=`cat pid` && expected=`cat expected` && test "$pid" = "$expected"],
AT_CAPTURE_FILE([parentpid])
AT_CAPTURE_FILE([newpid])
# Start the daemon and wait for the pidfile to get created.
-AT_CHECK([ovsdb-server --monitor --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > parent], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --monitor --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db& echo $! > parent], [0])
OVS_WAIT_UNTIL([test -s pid], [kill `cat parent`])
# Check that the pidfile names a running process,
# and that the parent process of that process is our child process.
# Start the daemon and make sure that the pidfile exists immediately.
# We don't wait for the pidfile to get created because the daemon is
# supposed to do so before the parent exits.
-AT_CHECK([ovsdb-server --detach --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --detach --pidfile=$PWD/pid --remote=punix:socket --unixctl=$PWD/unixctl db], [0])
AT_CHECK([test -s pid])
AT_CHECK([kill -0 `cat pid`])
# Kill the daemon and make sure that the pidfile gets deleted.
# Start the daemon and make sure that the pidfile exists immediately.
# We don't wait for the pidfile to get created because the daemon is
# supposed to do so before the parent exits.
-AT_CHECK([ovsdb-server --detach --pidfile=$PWD/daemon --monitor --remote=punix:socket --unixctl=$PWD/unixctl db], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-server --detach --pidfile=$PWD/daemon --monitor --remote=punix:socket --unixctl=$PWD/unixctl db], [0])
AT_CHECK([test -s daemon])
# Check that the pidfile names a running process,
# and that the parent process of that process is a running process,
# Kill the daemon process, making it look like a segfault,
# and wait for a new daemon process to get spawned.
CHECK([cp daemon olddaemon])
-CHECK([kill -SEGV `cat daemon`], [0], [ignore], [ignore])
+CHECK([kill -SEGV `cat daemon`], [0])
OVS_WAIT_WHILE([kill -0 `cat olddaemon`], [kill `cat olddaemon daemon`])
OVS_WAIT_UNTIL([test -s daemon && test `cat daemon` != `cat olddaemon`],
[kill `cat olddaemon daemon`])
AT_CHECK(
[[$PYTHON $srcdir/test-jsonrpc.py request unix:socket echo '[{"a": "b", "x": null}]']], [0],
[[{"error":null,"id":0,"result":[{"a":"b","x":null}]}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
AT_CHECK([kill `cat pid`])
AT_CLEANUP
AT_CHECK(
[[$PYTHON $srcdir/test-jsonrpc.py request unix:socket bad-request '[]']], [0],
[[{"error":{"error":"unknown method"},"id":0,"result":null}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
AT_CHECK([kill `cat pid`])
AT_CLEANUP
AT_CHECK([cp pid pid2])
AT_CHECK([kill -0 `cat pid2`])
AT_CHECK([[$PYTHON $srcdir/test-jsonrpc.py notify unix:socket shutdown '[]']], [0], [],
- [ignore], [kill `cat pid2`])
+ [], [kill `cat pid2`])
AT_CHECK(
[pid=`cat pid2`
# First try a quick sleep, so that the test completes very quickly
AT_CHECK(
[[test-jsonrpc request unix:socket echo '[{"a": "b", "x": null}]']], [0],
[[{"error":null,"id":0,"result":[{"a":"b","x":null}]}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
AT_CHECK([kill `cat pid`])
AT_CLEANUP
AT_CHECK(
[[test-jsonrpc request unix:socket bad-request '[]']], [0],
[[{"error":{"error":"unknown method"},"id":0,"result":null}
-]], [ignore], [test ! -e pid || kill `cat pid`])
+]], [], [test ! -e pid || kill `cat pid`])
AT_CHECK([kill `cat pid`])
AT_CLEANUP
AT_CHECK([cp pid pid2])
AT_CHECK([kill -0 `cat pid2`])
AT_CHECK([[test-jsonrpc notify unix:socket shutdown '[]']], [0], [],
- [ignore], [kill `cat pid2`])
+ [], [kill `cat pid2`])
AT_CHECK(
[pid=`cat pid2`
# First try a quick sleep, so that the test completes very quickly
AT_CLEANUP
AT_SETUP([test TCP/IP checksumming])
-AT_CHECK([test-csum], [0], [ignore])
+AT_CHECK([test-csum], [0], [....#....#....##................................#................................#
+])
AT_CLEANUP
AT_SETUP([test hash functions])
-AT_CHECK([test-hash], [0], [ignore])
+AT_CHECK([test-hash])
AT_CLEANUP
AT_SETUP([test hash map])
-AT_CHECK([test-hmap], [0], [ignore])
+AT_CHECK([test-hmap], [0], [.........
+])
AT_CLEANUP
AT_SETUP([test linked lists])
-AT_CHECK([test-list], [0], [ignore])
+AT_CHECK([test-list], [0], [..
+])
AT_CLEANUP
AT_SETUP([test packet library])
AT_CLEANUP
AT_SETUP([test SHA-1])
-AT_CHECK([test-sha1], [0], [ignore])
+AT_CHECK([test-sha1], [0], [.........
+])
AT_CLEANUP
AT_SETUP([test type properties])
-AT_CHECK([test-type-props], [0], [ignore])
+AT_CHECK([test-type-props])
AT_CLEANUP
AT_SETUP([test strtok_r bug fix])
-AT_CHECK([test-strtok_r], [0], [ignore])
+AT_CHECK([test-strtok_r], [0], [NULL NULL
+])
AT_CLEANUP
AT_SETUP([test byte order conversion])
AT_KEYWORDS([byte order])
-AT_CHECK([test-byte-order], [0], [ignore])
+AT_CHECK([test-byte-order])
AT_CLEANUP
AT_SETUP([test random number generator])
# The flow is formatted with cls_rule_format() for the low-verbosity case.
AT_SETUP([OFPT_FLOW_MOD - low verbosity])
AT_KEYWORDS([ofp-print])
-AT_CHECK([ovs-ofctl ofp-print "\
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
01 0e 00 50 00 00 00 00 00 00 00 00 00 01 50 54 \
00 00 00 06 50 54 00 00 00 05 ff ff 00 00 08 06 \
00 02 00 00 c0 a8 00 02 c0 a8 00 01 00 00 00 00 \
00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 \
00 00 01 0e 00 00 00 00 00 00 00 08 00 03 00 00 \
" 2], [0], [dnl
-OFPT_FLOW_MOD (xid=0x0): ADD priority=65535,arp,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0 idle:5 buf:0x10e actions=output:3
+OFPT_FLOW_MOD (xid=0x0): ADD priority=65535,arp,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0 idle:5 buf:0x10e actions=output:3
+], [dnl
+ofp_util|INFO|normalization changed ofp_match, details:
+ofp_util|INFO| pre: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0
+ofp_util|INFO|post: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0
])
AT_CLEANUP
-# The flow is formatted with ofp_match_to_string() for the low-verbosity case.
+# The flow is formatted with ofp_match_to_string() for the high-verbosity case.
AT_SETUP([OFPT_FLOW_MOD - high verbosity])
AT_KEYWORDS([ofp-print])
-AT_CHECK([ovs-ofctl ofp-print "\
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
01 0e 00 50 00 00 00 00 00 00 00 00 00 01 50 54 \
00 00 00 06 50 54 00 00 00 05 ff ff 00 00 08 06 \
00 02 00 00 c0 a8 00 02 c0 a8 00 01 00 00 00 00 \
00 00 01 0e 00 00 00 00 00 00 00 08 00 03 00 00 \
" 3], [0], [dnl
OFPT_FLOW_MOD (xid=0x0): ADD arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0 idle:5 pri:65535 buf:0x10e actions=output:3
+], [dnl
+ofp_util|INFO|normalization changed ofp_match, details:
+ofp_util|INFO| pre: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0,tp_src=0,tp_dst=0
+ofp_util|INFO|post: arp,in_port=1,dl_vlan=65535,dl_vlan_pcp=0,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,opcode=2,nw_tos=0
])
AT_CLEANUP
AT_CAPTURE_FILE([ovs-openflowd.log])
AT_CHECK(
[ovs-openflowd --detach --pidfile --enable-dummy --log-file --fail=closed dummy@br0 none --datapath-id=fedcba9876543210 $1],
- [0], [ignore], [ignore])
+ [0], [], [stderr])
+ AT_CHECK([[sed < stderr '
+/vlog|INFO|opened log file/d
+/openflowd|INFO|Open vSwitch version/d
+/openflowd|INFO|OpenFlow protocol version/d
+/ofproto|INFO|using datapath ID/d
+/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
])
m4_define([OFPROTO_STOP],
tun_id=0x1234000056780000/0xffff0000ffff0000,actions=drop
]])
AT_CHECK([ovs-ofctl parse-flows flows.txt
-], [0], [stdout], [stderr])
+], [0], [stdout])
AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0],
[[OFPT_FLOW_MOD: ADD tcp,tp_src=123 actions=FLOOD
OFPT_FLOW_MOD: ADD in_port=65534,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 actions=drop
NXT_FLOW_MOD: ADD table_id:1 actions=drop
NXT_FLOW_MOD: ADD table_id:255 tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop
]])
-AT_CHECK([sed 's/.*|//' stderr], [0], [dnl
-normalization changed ofp_match, details:
- pre: wildcards= 0x3820f8 in_port=65534 dl_src=00:0a:e4:25:6b:b0 dl_dst=00:00:00:00:00:00 dl_vlan= 9 dl_vlan_pcp= 0 dl_type= 0 nw_tos= 0 nw_proto= 0 nw_src= 0 nw_dst= 0 tp_src= 0 tp_dst= 0
-post: wildcards= 0x3ffff8 in_port=65534 dl_src=00:0a:e4:25:6b:b0 dl_dst=00:00:00:00:00:00 dl_vlan= 9 dl_vlan_pcp= 0 dl_type= 0 nw_tos= 0 nw_proto= 0 nw_src= 0 nw_dst= 0 tp_src= 0 tp_dst= 0
-normalization changed ofp_match, details:
- pre: wildcards= 0x3820ff in_port= 0 dl_src=00:00:00:00:00:00 dl_dst=00:00:00:00:00:00 dl_vlan= 0 dl_vlan_pcp= 0 dl_type= 0 nw_tos= 0 nw_proto= 0 nw_src= 0 nw_dst= 0 tp_src= 0 tp_dst= 0
-post: wildcards= 0x3fffff in_port= 0 dl_src=00:00:00:00:00:00 dl_dst=00:00:00:00:00:00 dl_vlan= 0 dl_vlan_pcp= 0 dl_type= 0 nw_tos= 0 nw_proto= 0 nw_src= 0 nw_dst= 0 tp_src= 0 tp_dst= 0
-normalization changed ofp_match, details:
- pre: wildcards= 0x3820ff in_port= 0 dl_src=00:00:00:00:00:00 dl_dst=00:00:00:00:00:00 dl_vlan= 0 dl_vlan_pcp= 0 dl_type= 0 nw_tos= 0 nw_proto= 0 nw_src= 0 nw_dst= 0 tp_src= 0 tp_dst= 0
-post: wildcards= 0x3fffff in_port= 0 dl_src=00:00:00:00:00:00 dl_dst=00:00:00:00:00:00 dl_vlan= 0 dl_vlan_pcp= 0 dl_type= 0 nw_tos= 0 nw_proto= 0 nw_src= 0 nw_dst= 0 tp_src= 0 tp_dst= 0
-])
AT_CLEANUP
AT_SETUP([ovs-ofctl -F nxm parse-flows])
file: read: [1]
]], [ignore])
AT_CHECK(
- [test-ovsdb -vlockfile:console:emer log-io file create read], [1],
+ [test-ovsdb log-io file create read], [1],
[], [test-ovsdb: I/O error: create: file failed (File exists)
])
AT_CHECK([test -f .file.~lock~])
"table": "ordinals",
"row": {"number": 0, "name": "zero"}}]'
]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
cat stdout >> output
dnl Add some crap to the database log and run another transaction, which should
dnl ignore the crap and truncate it out of the log.
"table": "ordinals",
"row": {"number": 1, "name": "one"}}]'
]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
AT_CHECK([grep 'syntax error: db: parse error.* in header line "xxx"' stderr],
[0], [ignore])
cat stdout >> output
"where": [],
"sort": ["number"]}]'
]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
cat stdout >> output
AT_CHECK([perl $srcdir/uuidfilt.pl output], [0],
[[[{"uuid":["uuid","<0>"]}]
"table": "ordinals",
"row": {"number": 0, "name": "zero"}}]'
]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
cat stdout >> output
dnl Add some crap to the database log and run another transaction, which should
dnl ignore the crap and truncate it out of the log.
"table": "ordinals",
"row": {"number": 1, "name": "one"}}]'
]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [stderr])
AT_CHECK([grep 'syntax "{"invalid":{}}": unknown table: No table named invalid.' stderr],
[0], [ignore])
cat stdout >> output
"where": [],
"sort": ["number"]}]'
]])
-AT_CHECK([ovsdb-server -vlockfile:ANY:EMER --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
+AT_CHECK([ovsdb-server --remote=punix:socket --unixctl=$PWD/unixctl db --run="sh txnfile"], [0], [stdout], [])
cat stdout >> output
AT_CHECK([perl $srcdir/uuidfilt.pl output], [0],
[[[{"uuid":["uuid","<0>"]}]
/*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 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.
int
main(void)
{
+#ifndef __CHECKER__
/* I picked some random numbers. */
const uint16_t s = 0xc9bd;
const uint32_t l = 0xffe56ae8;
assert(ntohll(htonll(ll)) == ll);
assert(CONSTANT_HTONLL(ntohll(ll)) == ll);
assert(ntohll(CONSTANT_HTONLL(ll)));
+#else /* __CHECKER__ */
+/* Making sparse happy with this code makes it unreadable, so don't bother. */
+#endif
return 0;
}
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 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.
/* RFC 1071 section 3. */
TEST_CASE("\x00\x01\xf2\x03"
"\xf4\xf5\xf6\xf7",
- (uint16_t) ~0xddf2),
+ 0xffff - 0xddf2 /* ~0xddf2 */),
/* http://www.sbprojects.com/projects/tcpip/theory/theory14.htm */
TEST_CASE("\x45\x00\x00\x28"
"\x66\x64\xfc\x96\x63\x97\x64\xee\x12\x53\x1d\xa9\x2d\xa9\x55\x55";
/* "...the one's complement sum of all other header octets is 0xCD7A." */
- assert(ntohs(csum(data, sizeof data - 2)) == (uint16_t) ~0xcd7a);
+ assert(ntohs(csum(data, sizeof data - 2)) == 0xffff - 0xcd7a);
/* "...the header checksum would be:
= ~(0x22D0 + ~0x5555 + 0x3285)
= ~0xFFFF
= 0x0000" */
- assert(recalc_csum16(0xdd2f, 0x5555, 0x3285) == 0x0000);
+ assert(recalc_csum16(htons(0xdd2f), htons(0x5555), htons(0x3285))
+ == htons(0x0000));
mark('#');
}
int i;
for (tc = test_cases; tc < &test_cases[ARRAY_SIZE(test_cases)]; tc++) {
- const uint16_t *data16 = (const uint16_t *) tc->data;
- const uint32_t *data32 = (const uint32_t *) tc->data;
+ const ovs_be16 *data16 = (OVS_FORCE const ovs_be16 *) tc->data;
+ const ovs_be32 *data32 = (OVS_FORCE const ovs_be32 *) tc->data;
uint32_t partial;
/* Test csum(). */
/* Test csum_add16(). */
partial = 0;
for (i = 0; i < tc->size / 2; i++) {
- partial = csum_add16(partial, get_unaligned_u16(&data16[i]));
+ partial = csum_add16(partial, get_unaligned_be16(&data16[i]));
}
assert(ntohs(csum_finish(partial)) == tc->csum);
mark('.');
/* Test csum_add32(). */
partial = 0;
for (i = 0; i < tc->size / 4; i++) {
- partial = csum_add32(partial, get_unaligned_u32(&data32[i]));
+ partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
}
assert(ntohs(csum_finish(partial)) == tc->csum);
mark('.');
partial = 0;
for (i = 0; i < tc->size / 4; i++) {
if (i % 2) {
- partial = csum_add32(partial, get_unaligned_u32(&data32[i]));
+ partial = csum_add32(partial, get_unaligned_be32(&data32[i]));
} else {
- uint16_t u0 = get_unaligned_u16(&data16[i * 2]);
- uint16_t u1 = get_unaligned_u16(&data16[i * 2 + 1]);
+ ovs_be16 u0 = get_unaligned_be16(&data16[i * 2]);
+ ovs_be16 u1 = get_unaligned_be16(&data16[i * 2 + 1]);
partial = csum_add16(partial, u0);
partial = csum_add16(partial, u1);
}
/* Test recalc_csum16(). */
for (i = 0; i < 32; i++) {
- uint16_t old_u16, new_u16;
- uint16_t old_csum;
- uint16_t data[16];
+ ovs_be16 old_u16, new_u16;
+ ovs_be16 old_csum;
+ ovs_be16 data[16];
int j, index;
for (j = 0; j < ARRAY_SIZE(data); j++) {
- data[j] = random_uint32();
+ data[j] = (OVS_FORCE ovs_be16) random_uint32();
}
old_csum = csum(data, sizeof data);
index = random_range(ARRAY_SIZE(data));
old_u16 = data[index];
- new_u16 = data[index] = random_uint32();
+ new_u16 = data[index] = (OVS_FORCE ovs_be16) random_uint32();
assert(csum(data, sizeof data)
== recalc_csum16(old_csum, old_u16, new_u16));
mark('.');
/* Test recalc_csum32(). */
for (i = 0; i < 32; i++) {
- uint32_t old_u32, new_u32;
- uint16_t old_csum;
- uint32_t data[16];
+ ovs_be32 old_u32, new_u32;
+ ovs_be16 old_csum;
+ ovs_be32 data[16];
int j, index;
for (j = 0; j < ARRAY_SIZE(data); j++) {
- data[j] = random_uint32();
+ data[j] = (OVS_FORCE ovs_be32) random_uint32();
}
old_csum = csum(data, sizeof data);
index = random_range(ARRAY_SIZE(data));
old_u32 = data[index];
- new_u32 = data[index] = random_uint32();
+ new_u32 = data[index] = (OVS_FORCE ovs_be32) random_uint32();
assert(csum(data, sizeof data)
== recalc_csum32(old_csum, old_u32, new_u32));
mark('.');
DAEMON_OPTION_ENUMS
};
static struct option long_options[] = {
- {"verbose", optional_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
+ {"verbose", optional_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
DAEMON_LONG_OPTIONS,
- {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
+ {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
STREAM_SSL_LONG_OPTIONS,
- {0, 0, 0, 0},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 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.
TEST(lock_timeout_runs_out),
TEST(lock_multiple),
TEST(help),
- { 0, 0 }
+ { NULL, NULL }
#undef TEST
};
parse_options(int argc, char *argv[])
{
static struct option long_options[] = {
- {"timeout", required_argument, 0, 't'},
- {"verbose", optional_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
- {0, 0, 0, 0},
+ {"timeout", required_argument, NULL, 't'},
+ {"verbose", optional_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
/*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 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.
{ 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
};
+ size_t i;
vec.data = xmalloc(SIZE);
- memset(vec.data, 'a', SIZE);
+ for (i = 0; i < SIZE; i++) {
+ vec.data[i] = 'a';
+ }
test_one(&vec);
free(vec.data);
}
char *token1, *token2;
token1 = strtok_r(string, ":", &save_ptr);
token2 = strtok_r(NULL, ":", &save_ptr);
- printf ("%s %s\n", token1, token2);
+ printf ("%s %s\n", token1 ? token1 : "NULL", token2 ? token2 : "NULL");
return 0;
}
/*
- * Copyright (c) 2009, 2010 Nicira Networks.
+ * Copyright (c) 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.
if (retval == sizeof hello) {
CHECK(hello.version, OFP_VERSION);
CHECK(hello.type, OFPT_HELLO);
- CHECK(hello.length, htons(sizeof hello));
+ CHECK(ntohs(hello.length), sizeof hello);
break;
} else {
CHECK_ERRNO(retval, -EAGAIN);
if (retval == sizeof hello) {
CHECK(hello.version, OFP_VERSION);
CHECK(hello.type, OFPT_HELLO);
- CHECK(hello.length, htons(sizeof hello));
+ CHECK(ntohs(hello.length), sizeof hello);
read_hello = true;
} else {
CHECK_ERRNO(retval, -EAGAIN);
/*
- * 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.
{"execute", no_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
- {0, 0, 0, 0},
+ {NULL, 0, NULL, 0},
};
const char *target;
int e_options;
DAEMON_OPTION_ENUMS
};
static struct option long_options[] = {
- {"hub", no_argument, 0, 'H'},
- {"noflow", no_argument, 0, 'n'},
- {"normal", no_argument, 0, 'N'},
- {"wildcard", no_argument, 0, 'w'},
- {"max-idle", required_argument, 0, OPT_MAX_IDLE},
- {"mute", no_argument, 0, OPT_MUTE},
- {"queue", required_argument, 0, 'q'},
- {"port-queue", required_argument, 0, 'Q'},
- {"with-flows", required_argument, 0, OPT_WITH_FLOWS},
- {"unixctl", required_argument, 0, OPT_UNIXCTL},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
+ {"hub", no_argument, NULL, 'H'},
+ {"noflow", no_argument, NULL, 'n'},
+ {"normal", no_argument, NULL, 'N'},
+ {"wildcard", no_argument, NULL, 'w'},
+ {"max-idle", required_argument, NULL, OPT_MAX_IDLE},
+ {"mute", no_argument, NULL, OPT_MUTE},
+ {"queue", required_argument, NULL, 'q'},
+ {"port-queue", required_argument, NULL, 'Q'},
+ {"with-flows", required_argument, NULL, OPT_WITH_FLOWS},
+ {"unixctl", required_argument, NULL, OPT_UNIXCTL},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
DAEMON_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
STREAM_SSL_LONG_OPTIONS,
- {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
- {0, 0, 0, 0},
+ {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
VLOG_DEFINE_THIS_MODULE(dpctl);
/* -s, --statistics: Print port statistics? */
-bool print_statistics;
+static bool print_statistics;
static const struct command all_commands[];
VLOG_OPTION_ENUMS
};
static struct option long_options[] = {
- {"statistics", no_argument, 0, 's'},
- {"timeout", required_argument, 0, 't'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
+ {"statistics", no_argument, NULL, 's'},
+ {"timeout", required_argument, NULL, 't'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
VLOG_LONG_OPTIONS,
- {0, 0, 0, 0},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
VLOG_OPTION_ENUMS
};
static struct option long_options[] = {
- {"timeout", required_argument, 0, 't'},
- {"strict", no_argument, 0, OPT_STRICT},
- {"flow-format", required_argument, 0, 'F'},
- {"more", no_argument, 0, 'm'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
+ {"timeout", required_argument, NULL, 't'},
+ {"strict", no_argument, NULL, OPT_STRICT},
+ {"flow-format", required_argument, NULL, 'F'},
+ {"more", no_argument, NULL, 'm'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
VLOG_LONG_OPTIONS,
STREAM_SSL_LONG_OPTIONS,
- {0, 0, 0, 0},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
DAEMON_OPTION_ENUMS
};
static struct option long_options[] = {
- {"datapath-id", required_argument, 0, OPT_DATAPATH_ID},
- {"mfr-desc", required_argument, 0, OPT_MFR_DESC},
- {"hw-desc", required_argument, 0, OPT_HW_DESC},
- {"sw-desc", required_argument, 0, OPT_SW_DESC},
- {"serial-desc", required_argument, 0, OPT_SERIAL_DESC},
- {"dp-desc", required_argument, 0, OPT_DP_DESC},
- {"config", required_argument, 0, 'F'},
- {"br-name", required_argument, 0, OPT_BR_NAME},
- {"fail", required_argument, 0, OPT_FAIL_MODE},
- {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE},
- {"max-idle", required_argument, 0, OPT_MAX_IDLE},
- {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF},
- {"listen", required_argument, 0, 'l'},
- {"snoop", required_argument, 0, OPT_SNOOP},
- {"rate-limit", optional_argument, 0, OPT_RATE_LIMIT},
- {"burst-limit", required_argument, 0, OPT_BURST_LIMIT},
- {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND},
- {"in-band", no_argument, 0, OPT_IN_BAND},
- {"netflow", required_argument, 0, OPT_NETFLOW},
- {"ports", required_argument, 0, OPT_PORTS},
- {"unixctl", required_argument, 0, OPT_UNIXCTL},
- {"enable-dummy", no_argument, 0, OPT_ENABLE_DUMMY},
- {"verbose", optional_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
+ {"datapath-id", required_argument, NULL, OPT_DATAPATH_ID},
+ {"mfr-desc", required_argument, NULL, OPT_MFR_DESC},
+ {"hw-desc", required_argument, NULL, OPT_HW_DESC},
+ {"sw-desc", required_argument, NULL, OPT_SW_DESC},
+ {"serial-desc", required_argument, NULL, OPT_SERIAL_DESC},
+ {"dp-desc", required_argument, NULL, OPT_DP_DESC},
+ {"config", required_argument, NULL, 'F'},
+ {"br-name", required_argument, NULL, OPT_BR_NAME},
+ {"fail", required_argument, NULL, OPT_FAIL_MODE},
+ {"inactivity-probe", required_argument, NULL, OPT_INACTIVITY_PROBE},
+ {"max-idle", required_argument, NULL, OPT_MAX_IDLE},
+ {"max-backoff", required_argument, NULL, OPT_MAX_BACKOFF},
+ {"listen", required_argument, NULL, 'l'},
+ {"snoop", required_argument, NULL, OPT_SNOOP},
+ {"rate-limit", optional_argument, NULL, OPT_RATE_LIMIT},
+ {"burst-limit", required_argument, NULL, OPT_BURST_LIMIT},
+ {"out-of-band", no_argument, NULL, OPT_OUT_OF_BAND},
+ {"in-band", no_argument, NULL, OPT_IN_BAND},
+ {"netflow", required_argument, NULL, OPT_NETFLOW},
+ {"ports", required_argument, NULL, OPT_PORTS},
+ {"unixctl", required_argument, NULL, OPT_UNIXCTL},
+ {"enable-dummy", no_argument, NULL, OPT_ENABLE_DUMMY},
+ {"verbose", optional_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
DAEMON_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
LEAK_CHECKER_LONG_OPTIONS,
STREAM_SSL_LONG_OPTIONS,
- {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
- {0, 0, 0, 0},
+ {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
struct ofproto_controller controller_opts;
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
- {0, 0, 0, 0},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
TABLE_OPTION_ENUMS
};
static struct option long_options[] = {
- {"db", required_argument, 0, OPT_DB},
- {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
- {"no-wait", no_argument, 0, OPT_NO_WAIT},
- {"dry-run", no_argument, 0, OPT_DRY_RUN},
- {"oneline", no_argument, 0, OPT_ONELINE},
- {"timeout", required_argument, 0, 't'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
+ {"db", required_argument, NULL, OPT_DB},
+ {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
+ {"no-wait", no_argument, NULL, OPT_NO_WAIT},
+ {"dry-run", no_argument, NULL, OPT_DRY_RUN},
+ {"oneline", no_argument, NULL, OPT_ONELINE},
+ {"timeout", required_argument, NULL, 't'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
VLOG_LONG_OPTIONS,
TABLE_LONG_OPTIONS,
STREAM_SSL_LONG_OPTIONS,
- {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
- {0, 0, 0, 0},
+ {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
+ {NULL, 0, NULL, 0},
};
char *tmp, *short_options;
static void
cmd_add_br(struct vsctl_context *ctx)
{
- bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
const char *br_name, *parent_name;
struct vsctl_info info;
int vlan;
static void
cmd_add_port(struct vsctl_context *ctx)
{
- bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, false,
&ctx->argv[2], 1, &ctx->argv[3], ctx->argc - 3);
static void
cmd_add_bond(struct vsctl_context *ctx)
{
- bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
bool fake_iface = shash_find(&ctx->options, "--fake-iface");
int n_ifaces;
int i;
br->name = xstrdup(br_cfg->name);
br->type = xstrdup(ofproto_normalize_type(br_cfg->datapath_type));
br->cfg = br_cfg;
- eth_addr_nicira_random(br->default_ea);
+
+ /* Derive the default Ethernet address from the bridge's UUID. This should
+ * be unique and it will be stable between ovs-vswitchd runs. */
+ memcpy(br->default_ea, &br_cfg->header_.uuid, ETH_ADDR_LEN);
+ eth_addr_mark_random(br->default_ea);
hmap_init(&br->ports);
hmap_init(&br->ifaces);
DAEMON_OPTION_ENUMS
};
static struct option long_options[] = {
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {"prune-timeout", required_argument, 0, OPT_PRUNE_TIMEOUT},
- {"appctl-command", required_argument, 0, OPT_APPCTL_COMMAND},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {"prune-timeout", required_argument, NULL, OPT_PRUNE_TIMEOUT},
+ {"appctl-command", required_argument, NULL, OPT_APPCTL_COMMAND},
DAEMON_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
LEAK_CHECKER_LONG_OPTIONS,
- {0, 0, 0, 0},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);
DAEMON_OPTION_ENUMS
};
static struct option long_options[] = {
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {"mlockall", no_argument, 0, OPT_MLOCKALL},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {"mlockall", no_argument, NULL, OPT_MLOCKALL},
DAEMON_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
LEAK_CHECKER_LONG_OPTIONS,
STREAM_SSL_LONG_OPTIONS,
- {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
- {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
- {"enable-dummy", no_argument, 0, OPT_ENABLE_DUMMY},
- {0, 0, 0, 0},
+ {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
+ {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
+ {"enable-dummy", no_argument, NULL, OPT_ENABLE_DUMMY},
+ {NULL, 0, NULL, 0},
};
char *short_options = long_options_to_short_options(long_options);