fi
.PHONY: check-assert-h-usage
+ALL_LOCAL += thread-safety-check
+thread-safety-check:
+ @if test -e '$(srcdir)'/.git && (git --version) >/dev/null 2>&1 && \
+ grep -n -f '$(srcdir)'/build-aux/thread-safety-blacklist \
+ `git ls-files '$(srcdir)' | grep '\.[ch]$$' \
+ | $(EGREP) -v '^datapath|^lib/sflow|^third-party'` \
+ | $(EGREP) -v ':[ ]*/?\*'; \
+ then \
+ echo "See above for list of calls to functions that are"; \
+ echo "blacklisted due to thread safety issues"; \
+ exit 1; \
+ fi
+EXTRA_DIST += build-aux/thread-safety-blacklist
+
if HAVE_GROFF
ALL_LOCAL += manpage-check
manpage-check: $(man_MANS) $(dist_man_MANS) $(noinst_man_MANS)
so the value is not necessarily meaningful. We might have to
just fix it as the same as in_port.
- * On OF1.1+ flow_mods, updates by MODIFY are now much better
- specified. Check that OVS implements the new behavior, fix it
- if not.
-
* OFPT_TABLE_MOD stats. This is new in OF1.1, so we need to
implement it. It should be implemented so that the default OVS
behavior does not change.
* OFPT_FLOW_MOD:
- * MODIFY and MODIFY_STRICT commands now never insert new flows
- in the table. We will still need variations that do,
- though, both to support older OpenFlow protocols and to get
- sensible behavior for the internal implementation of the
- NXAST_LEARN action.
-
* New flag OFPFF_RESET_COUNTS.
- * New cookie field behavior.
-
* Add ability to delete flow in all tables.
* Update DESIGN to describe OF1.2 behavior also.
--- /dev/null
+\basctime(
+\bbasename(
+\bcatgets(
+\bcrypt(
+\bctermid(
+\bctime(
+\bdbm_clearerr(
+\bdbm_close(
+\bdbm_delete(
+\bdbm_error(
+\bdbm_fetch(
+\bdbm_firstkey(
+\bdbm_nextkey(
+\bdbm_open(
+\bdbm_store(
+\bdirname(
+\bdlerror(
+\bdrand48(
+\becvt(
+\bencrypt(
+\bendgrent(
+\bendpwent(
+\bendutxent(
+\bfcvt(
+\bftw(
+\bgcvt(
+\bgetc_unlocked(
+\bgetchar_unlocked(
+\bgetdate(
+\bgetgrent(
+\bgetgrgid(
+\bgetgrnam(
+\bgethostbyaddr(
+\bgethostbyname(
+\bgethostent(
+\bgetlogin(
+\bgetmntent(
+\bgetnetbyaddr(
+\bgetnetbyname(
+\bgetnetent(
+\bgetprotobyname(
+\bgetprotobynumber(
+\bgetprotoent(
+\bgetpwent(
+\bgetpwnam(
+\bgetpwuid(
+\bgetservbyname(
+\bgetservbyport(
+\bgetservent(
+\bgetutxent(
+\bgetutxid(
+\bgetutxline(
+\bgmtime(
+\bhcreate(
+\bhdestroy(
+\bhsearch(
+\binet_ntoa(
+\bl64a(
+\blgamma(
+\blgammaf(
+\blgammal(
+\blocaleconv(
+\blocaltime(
+\blrand48(
+\bmrand48(
+\bnftw(
+\bnl_langinfo(
+\bptsname(
+\bputc_unlocked(
+\bputchar_unlocked(
+\bputenv(
+\bpututxline(
+\brand(
+\bsetenv(
+\bsetgrent(
+\bsetkey(
+\bsetpwent(
+\bsetutxent(
+\bsigprocmask(
+\bstrerror(
+\bstrsignal(
+\bstrtok(
+\bsystem(
+\btmpnam(
+\bttyname(
+\bunsetenv(
+\bwcrtomb(
+\bwcsrtombs(
+\bwcstombs(
+\bwctomb(
u32 seq, u32 flags, u8 cmd)
{
const int skb_orig_len = skb->len;
- const struct sw_flow_actions *sf_acts;
+ struct sw_flow_mask *mask;
struct nlattr *start;
struct ovs_flow_stats stats;
struct ovs_header *ovs_header;
u8 tcp_flags;
int err;
- sf_acts = ovsl_dereference(flow->sf_acts);
-
ovs_header = genlmsg_put(skb, portid, seq, &dp_flow_genl_family, flags, cmd);
if (!ovs_header)
return -EMSGSIZE;
if (!nla)
goto nla_put_failure;
- err = ovs_flow_to_nlattrs(&flow->key,
- &ovsl_dereference(flow->mask)->key, skb);
+ mask = rcu_dereference_check(flow->mask, lockdep_ovsl_is_held());
+ err = ovs_flow_to_nlattrs(&flow->key, &mask->key, skb);
if (err)
goto error;
*/
start = nla_nest_start(skb, OVS_FLOW_ATTR_ACTIONS);
if (start) {
+ const struct sw_flow_actions *sf_acts;
+
+ sf_acts = rcu_dereference_check(flow->sf_acts,
+ lockdep_ovsl_is_held());
+
err = actions_to_attr(sf_acts->actions, sf_acts->actions_len, skb);
if (!err)
nla_nest_end(skb, start);
/* The unmasked key has to be the same for flow updates. */
error = -EINVAL;
- if (!ovs_flow_cmp_unmasked_key(flow, &key, match.range.end))
+ if (!ovs_flow_cmp_unmasked_key(flow, &key, match.range.end)) {
+ OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n");
goto err_unlock_ovs;
+ }
/* Update actions. */
old_acts = ovsl_dereference(flow->sf_acts);
struct sw_flow_match match;
int err;
- if (!a[OVS_FLOW_ATTR_KEY])
+ if (!a[OVS_FLOW_ATTR_KEY]) {
+ OVS_NLERR("Flow get message rejected, Key attribute missing.\n");
return -EINVAL;
+ }
ovs_match_init(&match, &key, NULL);
err = ovs_match_from_nlattrs(&match, a[OVS_FLOW_ATTR_KEY], NULL);
struct datapath *dp;
struct flow_table *table;
- ovs_lock();
+ rcu_read_lock();
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
if (!dp) {
- ovs_unlock();
+ rcu_read_unlock();
return -ENODEV;
}
- table = ovsl_dereference(dp->table);
-
+ table = rcu_dereference(dp->table);
for (;;) {
struct sw_flow *flow;
u32 bucket, obj;
cb->args[0] = bucket;
cb->args[1] = obj;
}
- ovs_unlock();
+ rcu_read_unlock();
return skb->len;
}
int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb);
void ovs_dp_notify_wq(struct work_struct *work);
+
+#define OVS_NLERR(fmt, ...) \
+ pr_info_once(fmt "netlink: ", ##__VA_ARGS__)
+
#endif /* datapath.h */
}
}
- if ((key_attrs & key_expected) != key_expected)
+ if ((key_attrs & key_expected) != key_expected) {
/* Key attributes check failed. */
+ OVS_NLERR("Missing expected key attributes (key_attrs=%llx, expected=%llx).\n",
+ key_attrs, key_expected);
return false;
+ }
- if ((mask_attrs & mask_allowed) != mask_attrs)
+ if ((mask_attrs & mask_allowed) != mask_attrs) {
/* Mask attributes check failed. */
+ OVS_NLERR("Contain more than allowed mask fields (mask_attrs=%llx, mask_allowed=%llx).\n",
+ mask_attrs, mask_allowed);
return false;
+ }
return true;
}
u16 type = nla_type(nla);
int expected_len;
- if (type > OVS_KEY_ATTR_MAX || attrs & (1ULL << type))
- return -EINVAL;
+ if (type > OVS_KEY_ATTR_MAX) {
+ OVS_NLERR("Unknown key attribute (type=%d, max=%d).\n",
+ type, OVS_KEY_ATTR_MAX);
+ }
- expected_len = ovs_key_lens[type];
- if (nla_len(nla) != expected_len && expected_len != -1)
+ if (attrs & (1ULL << type)) {
+ OVS_NLERR("Duplicate key attribute (type %d).\n", type);
return -EINVAL;
+ }
- if (attrs & (1ULL << type))
- /* Duplicated field. */
+ expected_len = ovs_key_lens[type];
+ if (nla_len(nla) != expected_len && expected_len != -1) {
+ OVS_NLERR("Key attribute has unexpected length (type=%d"
+ ", length=%d, expected=%d).\n", type,
+ nla_len(nla), expected_len);
return -EINVAL;
+ }
if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
attrs |= 1ULL << type;
a[type] = nla;
}
}
- if (rem)
+ if (rem) {
+ OVS_NLERR("Message has %d unknown bytes.\n", rem);
return -EINVAL;
+ }
*attrsp = attrs;
return 0;
[OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
};
- if (type > OVS_TUNNEL_KEY_ATTR_MAX ||
- ovs_tunnel_key_lens[type] != nla_len(a))
+ if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
+ OVS_NLERR("Unknown IPv4 tunnel attribute (type=%d, max=%d)\n",
+ type, OVS_TUNNEL_KEY_ATTR_MAX);
+ return -EINVAL;
+ }
+
+ if (ovs_tunnel_key_lens[type] != nla_len(a)) {
+ OVS_NLERR("IPv4 tunnel attribute type has unexpected "
+ " legnth (type=%d, length=%d, expected=%d.)\n",
+ type, nla_len(a), ovs_tunnel_key_lens[type]);
return -EINVAL;
+ }
switch (type) {
case OVS_TUNNEL_KEY_ATTR_ID:
SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
- if (rem > 0)
+ if (rem > 0) {
+ OVS_NLERR("IPv4 tunnel attribute has %d unknown bytes.\n", rem);
return -EINVAL;
+ }
- if (!match->key->tun_key.ipv4_dst)
+ if (!match->key->tun_key.ipv4_dst) {
+ OVS_NLERR("IPv4 tunnel destination address is zero.\n");
return -EINVAL;
+ }
- if (!ttl)
+ if (!ttl) {
+ OVS_NLERR("IPv4 tunnel TTL is zero.\n");
return -EINVAL;
+ }
return 0;
}
if (*attrs & (1ULL << OVS_KEY_ATTR_SKB_MARK)) {
uint32_t mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) && !defined(CONFIG_NETFILTER)
- if (!is_mask && mark != 0)
+ if (!is_mask && mark != 0) {
+ OVS_NLERR("skb->mark must be zero on this kernel (mark=%d).\n", mark);
return -EINVAL;
+ }
#endif
SW_FLOW_KEY_PUT(match, phy.skb_mark, mark, is_mask);
*attrs &= ~(1ULL << OVS_KEY_ATTR_SKB_MARK);
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
if (!is_mask)
- if (!(tci & htons(VLAN_TAG_PRESENT)))
+ if (!(tci & htons(VLAN_TAG_PRESENT))) {
+ OVS_NLERR("VLAN TCI does not have VLAN_TAG_PRESENT bit set.\n");
return -EINVAL;
+ }
SW_FLOW_KEY_PUT(match, eth.tci, tci, is_mask);
attrs &= ~(1ULL << OVS_KEY_ATTR_VLAN);
__be16 eth_type;
eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
- if (!is_mask && ntohs(eth_type) < ETH_P_802_3_MIN)
+ if (!is_mask && ntohs(eth_type) < ETH_P_802_3_MIN) {
+ OVS_NLERR("EtherType is less than mimimum (type=%x, min=%x).\n",
+ ntohs(eth_type), ETH_P_802_3_MIN);
return -EINVAL;
+ }
SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
attrs &= ~(1ULL << OVS_KEY_ATTR_ETHERTYPE);
const struct ovs_key_ipv4 *ipv4_key;
ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
- if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX)
+ if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
+ OVS_NLERR("Unknown IPv4 fragment type (value=%d, max=%d).\n",
+ ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
return -EINVAL;
+ }
SW_FLOW_KEY_PUT(match, ip.proto,
ipv4_key->ipv4_proto, is_mask);
SW_FLOW_KEY_PUT(match, ip.tos,
const struct ovs_key_ipv6 *ipv6_key;
ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
- if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX)
+ if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
+ OVS_NLERR("Unknown IPv6 fragment type (value=%d, max=%d).\n",
+ ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
return -EINVAL;
+ }
SW_FLOW_KEY_PUT(match, ipv6.label,
ipv6_key->ipv6_label, is_mask);
SW_FLOW_KEY_PUT(match, ip.proto,
const struct ovs_key_arp *arp_key;
arp_key = nla_data(a[OVS_KEY_ATTR_ARP]);
- if (!is_mask && (arp_key->arp_op & htons(0xff00)))
+ if (!is_mask && (arp_key->arp_op & htons(0xff00))) {
+ OVS_NLERR("Unknown ARP opcode (opcode=%d).\n",
+ arp_key->arp_op);
return -EINVAL;
+ }
SW_FLOW_KEY_PUT(match, ipv4.addr.src,
arp_key->arp_sip, is_mask);
encap_valid = true;
key_attrs &= ~(1ULL << OVS_KEY_ATTR_ETHERTYPE);
err = parse_flow_nlattrs(encap, a, &key_attrs);
- } else
+ } else {
+ OVS_NLERR("Encap attribute is set for a non-VLAN frame.\n");
err = -EINVAL;
+ }
if (err)
return err;
mask_attrs &= ~(1ULL << OVS_KEY_ATTR_ETHERTYPE);
encap = a[OVS_KEY_ATTR_ENCAP];
err = parse_flow_mask_nlattrs(encap, a, &mask_attrs);
- } else
+ } else {
+ OVS_NLERR("VLAN frames must have an exact match"
+ " on the TPID (mask=%x).\n",
+ ntohs(eth_type));
err = -EINVAL;
+ }
if (err)
return err;
#define pr_warn pr_warning
#endif
+/*
+ * Print a one-time message (analogous to WARN_ONCE() et al):
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
+#undef printk_once
+#define printk_once(fmt, ...) \
+({ \
+ static bool __print_once; \
+ \
+ if (!__print_once) { \
+ __print_once = true; \
+ printk(fmt, ##__VA_ARGS__); \
+ } \
+})
+
+#define pr_emerg_once(fmt, ...) \
+ printk_once(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_alert_once(fmt, ...) \
+ printk_once(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_crit_once(fmt, ...) \
+ printk_once(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err_once(fmt, ...) \
+ printk_once(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warn_once(fmt, ...) \
+ printk_once(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_notice_once(fmt, ...) \
+ printk_once(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info_once(fmt, ...) \
+ printk_once(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_cont_once(fmt, ...) \
+ printk_once(KERN_CONT pr_fmt(fmt), ##__VA_ARGS__)
+
+#endif
+
#if defined(CONFIG_PREEMPT) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
#error "CONFIG_PREEMPT is broken before 2.6.21--see commit 4498121ca3, \"[NET]: Handle disabled preemption in gfp_any()\""
#endif
#include <linux/skbuff.h>
#include <net/ip_tunnels.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
#include_next <net/gre.h>
-#else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,37) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) */
#define GREPROTO_CISCO 0
#define GREPROTO_MAX 2
int low;
int high;
unsigned int range;
- u32 hash = OVS_CB(skb)->flow->hash;
+ struct sw_flow_key *pkt_key = OVS_CB(skb)->pkt_key;
+ u32 hash = jhash2((const u32 *)pkt_key,
+ sizeof(*pkt_key) / sizeof(u32), 0);
inet_get_local_port_range(&low, &high);
range = (high - low) + 1;
if (flow->dl_type == htons(ETH_TYPE_IP)) {
memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
- } else {
+ } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
memset(&wc->masks.ipv6_src, 0xff, sizeof wc->masks.ipv6_src);
memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
}
af_link_sock = socket(AF_LINK, SOCK_DGRAM, 0);
status = af_link_sock >= 0 ? 0 : errno;
if (status) {
- VLOG_ERR("failed to create link socket: %s", Ovs_strerror(status));
+ VLOG_ERR("failed to create link socket: %s", ovs_strerror(status));
close(af_inet_sock);
af_inet_sock = -1;
}
ovs_be16 vlan_tci = nl_attr_get_be16(a);
if (!is_exact) {
ovs_be16 mask = nl_attr_get_be16(ma);
- ds_put_format(ds, "vid=%"PRIu16"/%"PRIx16",pcp=%d/0x%x,cfi=%d/%d",
+ ds_put_format(ds, "vid=%"PRIu16"/0x%"PRIx16",pcp=%d/0x%x,cfi=%d/%d",
vlan_tci_to_vid(vlan_tci),
vlan_tci_to_vid(mask),
vlan_tci_to_pcp(vlan_tci),
* 802.3 SNAP packet with valid eth_type).
*/
if (is_mask) {
- nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, data->dl_type);
+ nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, htons(UINT16_MAX));
}
goto unencap;
}
/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <sys/time.h>
#include "entropy.h"
+#include "hash.h"
+#include "ovs-thread.h"
#include "timeval.h"
#include "util.h"
* cryptographic-quality randomness. */
/* Current random state. */
-static uint32_t seed;
+DEFINE_PER_THREAD_DATA(uint32_t, seed, 0);
static uint32_t random_next(void);
void
random_init(void)
{
- while (!seed) {
+ uint32_t *seedp = seed_get();
+ while (!*seedp) {
struct timeval tv;
uint32_t entropy;
+ pthread_t self;
xgettimeofday(&tv);
get_entropy_or_die(&entropy, 4);
+ self = pthread_self();
- seed = tv.tv_sec ^ tv.tv_usec ^ entropy;
+ *seedp = (tv.tv_sec ^ tv.tv_usec ^ entropy
+ ^ hash_bytes(&self, sizeof self, 0));
}
}
random_set_seed(uint32_t seed_)
{
ovs_assert(seed_);
- seed = seed_;
+ *seed_get() = seed_;
}
void
static uint32_t
random_next(void)
{
- seed ^= seed << 13;
- seed ^= seed >> 17;
- seed ^= seed << 5;
+ uint32_t *seedp = seed_get_unsafe();
- return seed;
+ *seedp ^= *seedp << 13;
+ *seedp ^= *seedp >> 17;
+ *seedp ^= *seedp << 5;
+
+ return *seedp;
}
} else if (is_pow2((bitmap >> 1) + 1)) {
ds_put_cstr(&s, "version ");
ofputil_format_version(&s, leftmost_1bit_idx(bitmap));
- ds_put_cstr(&s, "and earlier");
+ ds_put_cstr(&s, " and earlier");
} else {
ds_put_cstr(&s, "versions ");
ofputil_format_version_bitmap(&s, bitmap);
* for debugging the asynchronous flow_mod implementation.) */
static bool clogged;
+/* By default, flows in the datapath are wildcarded (megaflows). They
+ * may be disabled with the "ovs-appctl dpif/disable-megaflows" command. */
+static bool enable_megaflows = true;
+
/* All existing ofproto_dpif instances, indexed by ->up.name. */
static struct hmap all_ofproto_dpifs = HMAP_INITIALIZER(&all_ofproto_dpifs);
subfacet->path = want_path;
ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
- odp_flow_key_from_mask(&op->mask, &facet->xout.wc.masks,
- &miss->flow, UINT32_MAX);
+ if (enable_megaflows) {
+ odp_flow_key_from_mask(&op->mask, &facet->xout.wc.masks,
+ &miss->flow, UINT32_MAX);
+ }
op->xout_garbage = false;
op->dpif_op.type = DPIF_OP_FLOW_PUT;
}
ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf);
- odp_flow_key_from_mask(&mask, &facet->xout.wc.masks,
- &facet->flow, UINT32_MAX);
+ if (enable_megaflows) {
+ odp_flow_key_from_mask(&mask, &facet->xout.wc.masks,
+ &facet->flow, UINT32_MAX);
+ }
ret = dpif_flow_put(subfacet->backer->dpif, flags, subfacet->key,
subfacet->key_len, mask.data, mask.size,
ds_destroy(&ds);
}
+/* Disable using the megaflows.
+ *
+ * This command is only needed for advanced debugging, so it's not
+ * documented in the man page. */
+static void
+ofproto_unixctl_dpif_disable_megaflows(struct unixctl_conn *conn,
+ int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED,
+ void *aux OVS_UNUSED)
+{
+ struct ofproto_dpif *ofproto;
+
+ enable_megaflows = false;
+
+ HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+ flush(&ofproto->up);
+ }
+
+ unixctl_command_reply(conn, "megaflows disabled");
+}
+
+/* Re-enable using megaflows.
+ *
+ * This command is only needed for advanced debugging, so it's not
+ * documented in the man page. */
+static void
+ofproto_unixctl_dpif_enable_megaflows(struct unixctl_conn *conn,
+ int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED,
+ void *aux OVS_UNUSED)
+{
+ struct ofproto_dpif *ofproto;
+
+ enable_megaflows = true;
+
+ HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+ flush(&ofproto->up);
+ }
+
+ unixctl_command_reply(conn, "megaflows enabled");
+}
+
static void
ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn,
int argc OVS_UNUSED, const char *argv[],
ofproto_unixctl_dpif_del_flows, NULL);
unixctl_command_register("dpif/dump-megaflows", "bridge", 1, 1,
ofproto_unixctl_dpif_dump_megaflows, NULL);
+ unixctl_command_register("dpif/disable-megaflows", "", 0, 0,
+ ofproto_unixctl_dpif_disable_megaflows, NULL);
+ unixctl_command_register("dpif/enable-megaflows", "", 0, 0,
+ ofproto_unixctl_dpif_enable_megaflows, NULL);
}
\f
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
AT_CLEANUP
dnl The OpenFlow 1.2 spec states that the cookie may not be modified
-AT_SETUP([ofproto - no mod flow with cookie change (OpenFlow1.2)])
+AT_SETUP([ofproto - no mod flow with cookie change (OpenFlow 1.2)])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 cookie=0x1,in_port=1,actions=1])
AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], [0], [dnl
#define TEST_ATOMIC_TYPE(ATOMIC_TYPE, BASE_TYPE) \
{ \
ATOMIC_TYPE x = ATOMIC_VAR_INIT(1); \
- BASE_TYPE value, orig; \
+ BASE_TYPE value; \
\
atomic_read(&x, &value); \
ovs_assert(value == 1); \
atomic_init(&x, 3); \
atomic_read(&x, &value); \
ovs_assert(value == 3); \
- \
- atomic_add(&x, 1, &orig); \
- ovs_assert(orig == 3); \
- atomic_read(&x, &value); \
- ovs_assert(value == 4); \
- \
- atomic_sub(&x, 2, &orig); \
- ovs_assert(orig == 4); \
- atomic_read(&x, &value); \
- ovs_assert(value == 2); \
- \
- atomic_or(&x, 6, &orig); \
- ovs_assert(orig == 2); \
- atomic_read(&x, &value); \
- ovs_assert(value == 6); \
- \
- atomic_and(&x, 10, &orig); \
- ovs_assert(orig == 6); \
- atomic_read(&x, &value); \
- ovs_assert(value == 2); \
- \
- atomic_xor(&x, 10, &orig); \
- ovs_assert(orig == 2); \
- atomic_read(&x, &value); \
- ovs_assert(value == 8); \
}
int
/*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "flow.h"
#include "ofp-util.h"
#include "packets.h"
+#include "random.h"
#include "unaligned.h"
#undef NDEBUG
struct flow flow;
unsigned int x;
- x = rand () % N_FLOW_VALUES;
+ x = random_range(N_FLOW_VALUES);
memset(&flow, 0, sizeof flow);
flow.nw_src = nw_src_values[get_value(&x, N_NW_SRC_VALUES)];
flow.nw_dst = nw_dst_values[get_value(&x, N_NW_DST_VALUES)];
shuffle(unsigned int *p, size_t n)
{
for (; n > 1; n--, p++) {
- unsigned int *q = &p[rand() % n];
+ unsigned int *q = &p[random_range(n)];
unsigned int tmp = *p;
*p = *q;
*q = tmp;
shuffle_u32s(uint32_t *p, size_t n)
{
for (; n > 1; n--, p++) {
- uint32_t *q = &p[rand() % n];
+ uint32_t *q = &p[random_range(n)];
uint32_t tmp = *p;
*p = *q;
*q = tmp;
int i;
do {
- wcf = rand() & ((1u << CLS_N_FIELDS) - 1);
+ wcf = random_uint32() & ((1u << CLS_N_FIELDS) - 1);
value_mask = ~wcf & ((1u << CLS_N_FIELDS) - 1);
} while ((1 << count_ones(value_mask)) < N_RULES);
tcls_init(&tcls);
for (i = 0; i < N_RULES; i++) {
- unsigned int priority = rand();
+ unsigned int priority = random_uint32();
do {
- value_pats[i] = rand() & value_mask;
+ value_pats[i] = random_uint32() & value_mask;
} while (array_contains(value_pats, i, value_pats[i]));
rules[i] = make_rule(wcf, priority, value_pats[i]);
assert(n_tables < 10);
for (i = 0; i < n_tables; i++) {
do {
- wcfs[i] = rand() & ((1u << CLS_N_FIELDS) - 1);
+ wcfs[i] = random_uint32() & ((1u << CLS_N_FIELDS) - 1);
} while (array_contains(wcfs, i, wcfs[i]));
}
struct classifier cls;
struct tcls tcls;
- srand(iteration);
+ random_set_seed(iteration + 1);
for (i = 0; i < MAX_RULES; i++) {
priorities[i] = i * 129;
}
for (i = 0; i < MAX_RULES; i++) {
struct test_rule *rule;
unsigned int priority = priorities[i];
- int wcf = wcfs[rand() % n_tables];
- int value_pat = rand() & ((1u << CLS_N_FIELDS) - 1);
+ int wcf = wcfs[random_range(n_tables)];
+ int value_pat = random_uint32() & ((1u << CLS_N_FIELDS) - 1);
rule = make_rule(wcf, priority, value_pat);
tcls_insert(&tcls, rule);
classifier_insert(&cls, &rule->cls_rule);
struct test_rule *target;
struct cls_cursor cursor;
- target = clone_rule(tcls.rules[rand() % tcls.n_rules]);
+ target = clone_rule(tcls.rules[random_range(tcls.n_rules)]);
cls_cursor_init(&cursor, &cls, &target->cls_rule);
CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, cls_rule, &cursor) {
{ 0xffffffff, 0xaaaaaaaa, 0x55555555, 0x80000000,
0x00000001, 0xface0000, 0x00d00d1e, 0xdeadbeef };
- return values[random_uint32() % ARRAY_SIZE(values)];
+ return values[random_range(ARRAY_SIZE(values))];
}
static bool
#include "hindex.h"
#include <string.h>
#include "hash.h"
+#include "random.h"
#include "util.h"
#undef NDEBUG
shuffle(int *p, size_t n)
{
for (; n > 1; n--, p++) {
- int *q = &p[rand() % n];
+ int *q = &p[random_range(n)];
int tmp = *p;
*p = *q;
*q = tmp;
/*
- * Copyright (c) 2008, 2009, 2010 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "hmap.h"
#include <string.h>
#include "hash.h"
+#include "random.h"
#include "util.h"
#undef NDEBUG
shuffle(int *p, size_t n)
{
for (; n > 1; n--, p++) {
- int *q = &p[rand() % n];
+ int *q = &p[random_range(n)];
int tmp = *p;
*p = *q;
*q = tmp;
/*
- * Copyright (c) 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
shuffle(unsigned int *p, size_t n)
{
for (; n > 1; n--, p++) {
- unsigned int *q = &p[rand() % n];
+ unsigned int *q = &p[random_range(n)];
unsigned int tmp = *p;
*p = *q;
*q = tmp;
/* Change a random 0-bit into a 1-bit. */
do {
- bit = htonll(UINT64_C(1) << (random_uint32() % 64));
+ bit = htonll(UINT64_C(1) << (random_range(64)));
} while (x & bit);
x |= bit;