static int do_del_port(struct dp_netdev *, uint16_t port_no);
static int dpif_netdev_open(const struct dpif_class *, const char *name,
bool create, struct dpif **);
-static int dp_netdev_output_control(struct dp_netdev *, const struct ofpbuf *,
+static int dp_netdev_output_userspace(struct dp_netdev *, const struct ofpbuf *,
int queue_no, const struct flow *,
uint64_t arg);
static int dp_netdev_execute_actions(struct dp_netdev *,
return EINVAL;
}
+ if (flow->in_port < OFPP_MAX
+ ? flow->in_port >= MAX_PORTS
+ : flow->in_port != OFPP_LOCAL && flow->in_port != OFPP_NONE) {
+ return EINVAL;
+ }
+
return 0;
}
}
break;
- case ODP_ACTION_ATTR_CONTROLLER:
- case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
+ case ODP_ACTION_ATTR_USERSPACE:
break;
case ODP_ACTION_ATTR_SET_DL_TCI:
static int
dpif_netdev_execute(struct dpif *dpif,
+ const struct nlattr *key_attrs, size_t key_len,
const struct nlattr *actions, size_t actions_len,
const struct ofpbuf *packet)
{
* if we don't. */
copy = *packet;
}
+
flow_extract(©, 0, -1, &key);
- error = dp_netdev_execute_actions(dp, ©, &key, actions, actions_len);
+ error = dpif_netdev_flow_from_nlattrs(key_attrs, key_len, &key);
+ if (!error) {
+ error = dp_netdev_execute_actions(dp, ©, &key,
+ actions, actions_len);
+ }
if (mutates) {
ofpbuf_uninit(©);
}
dp->n_hit++;
} else {
dp->n_missed++;
- dp_netdev_output_control(dp, packet, DPIF_UC_MISS, &key, 0);
+ dp_netdev_output_userspace(dp, packet, DPIF_UC_MISS, &key, 0);
}
}
}
static int
-dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet,
+dp_netdev_output_userspace(struct dp_netdev *dp, const struct ofpbuf *packet,
int queue_no, const struct flow *flow, uint64_t arg)
{
struct dp_netdev_queue *q = &dp->queues[queue_no];
return 0;
}
-/* Returns true if 'packet' is an invalid Ethernet+IPv4 ARP packet: one with
- * screwy or truncated header fields or one whose inner and outer Ethernet
- * address differ. */
-static bool
-dp_netdev_is_spoofed_arp(struct ofpbuf *packet, const struct flow *key)
-{
- struct arp_eth_header *arp;
- struct eth_header *eth;
- ptrdiff_t l3_size;
-
- if (key->dl_type != htons(ETH_TYPE_ARP)) {
- return false;
- }
-
- l3_size = (char *) ofpbuf_end(packet) - (char *) packet->l3;
- if (l3_size < sizeof(struct arp_eth_header)) {
- return true;
- }
-
- eth = packet->l2;
- arp = packet->l3;
- return (arp->ar_hrd != htons(ARP_HRD_ETHERNET)
- || arp->ar_pro != htons(ARP_PRO_IP)
- || arp->ar_hln != ETH_HEADER_LEN
- || arp->ar_pln != 4
- || !eth_addr_equals(arp->ar_sha, eth->eth_src));
-}
-
static int
dp_netdev_execute_actions(struct dp_netdev *dp,
struct ofpbuf *packet, struct flow *key,
dp_netdev_output_port(dp, packet, nl_attr_get_u32(a));
break;
- case ODP_ACTION_ATTR_CONTROLLER:
- dp_netdev_output_control(dp, packet, DPIF_UC_ACTION,
+ case ODP_ACTION_ATTR_USERSPACE:
+ dp_netdev_output_userspace(dp, packet, DPIF_UC_ACTION,
key, nl_attr_get_u64(a));
break;
case ODP_ACTION_ATTR_SET_TP_DST:
dp_netdev_set_tp_port(packet, key, a);
break;
-
- case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
- if (dp_netdev_is_spoofed_arp(packet, key)) {
- return 0;
- }
}
}
return 0;