#include "ofpbuf.h"
#include "packets.h"
#include "poll-loop.h"
+#include "random.h"
#include "shash.h"
#include "timeval.h"
#include "util.h"
return 0;
}
+static void
+dp_netdev_sample(struct dp_netdev *dp,
+ struct ofpbuf *packet, struct flow *key,
+ const struct nlattr *action)
+{
+ const struct nlattr *subactions = NULL;
+ const struct nlattr *a;
+ size_t left;
+
+ NL_NESTED_FOR_EACH_UNSAFE (a, left, action) {
+ int type = nl_attr_type(a);
+
+ switch ((enum ovs_sample_attr) type) {
+ case OVS_SAMPLE_ATTR_PROBABILITY:
+ if (random_uint32() >= nl_attr_get_u32(a)) {
+ return;
+ }
+ break;
+
+ case OVS_SAMPLE_ATTR_ACTIONS:
+ subactions = a;
+ break;
+
+ case OVS_SAMPLE_ATTR_UNSPEC:
+ case __OVS_SAMPLE_ATTR_MAX:
+ default:
+ NOT_REACHED();
+ }
+ }
+
+ dp_netdev_execute_actions(dp, packet, key, nl_attr_get(subactions),
+ nl_attr_get_size(subactions));
+}
+
+static void
+dp_netdev_action_userspace(struct dp_netdev *dp,
+ struct ofpbuf *packet, struct flow *key,
+ const struct nlattr *a)
+{
+ const struct nlattr *userdata_attr;
+ uint64_t userdata;
+
+ userdata_attr = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
+ userdata = userdata_attr ? nl_attr_get_u64(userdata_attr) : 0;
+ dp_netdev_output_userspace(dp, packet, DPIF_UC_ACTION, key, userdata);
+}
+
static int
dp_netdev_execute_actions(struct dp_netdev *dp,
struct ofpbuf *packet, struct flow *key,
unsigned int left;
NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
- switch (nl_attr_type(a)) {
+ int type = nl_attr_type(a);
+
+ switch ((enum ovs_action_attr) type) {
case OVS_ACTION_ATTR_OUTPUT:
dp_netdev_output_port(dp, packet, nl_attr_get_u32(a));
break;
case OVS_ACTION_ATTR_USERSPACE:
- dp_netdev_output_userspace(dp, packet, DPIF_UC_ACTION,
- key, nl_attr_get_u64(a));
+ dp_netdev_action_userspace(dp, packet, key, a);
break;
case OVS_ACTION_ATTR_PUSH_VLAN:
case OVS_ACTION_ATTR_SET_TP_DST:
dp_netdev_set_tp_port(packet, key, a);
break;
+
+ case OVS_ACTION_ATTR_SAMPLE:
+ dp_netdev_sample(dp, packet, key, a);
+ break;
+
+ case OVS_ACTION_ATTR_SET_TUNNEL:
+ case OVS_ACTION_ATTR_SET_PRIORITY:
+ case OVS_ACTION_ATTR_POP_PRIORITY:
+ /* not implemented */
+ break;
+
+ case OVS_ACTION_ATTR_UNSPEC:
+ case __OVS_ACTION_ATTR_MAX:
+ NOT_REACHED();
}
}
return 0;
dpif_netdev_port_query_by_number,
dpif_netdev_port_query_by_name,
dpif_netdev_get_max_ports,
+ NULL, /* port_get_pid */
dpif_netdev_port_dump_start,
dpif_netdev_port_dump_next,
dpif_netdev_port_dump_done,