#include "odp-util.h"
#include <errno.h>
#include <inttypes.h>
+#include <netinet/icmp6.h>
#include <stdlib.h>
#include <string.h>
#include "byte-order.h"
switch ((enum odp_action_type) type) {
case ODP_ACTION_ATTR_OUTPUT: return 4;
- case ODP_ACTION_ATTR_CONTROLLER: return 8;
+ case ODP_ACTION_ATTR_USERSPACE: return 8;
case ODP_ACTION_ATTR_SET_DL_TCI: return 2;
case ODP_ACTION_ATTR_STRIP_VLAN: return 0;
case ODP_ACTION_ATTR_SET_DL_SRC: return ETH_ADDR_LEN;
case ODP_ACTION_ATTR_SET_TUNNEL: return 8;
case ODP_ACTION_ATTR_SET_PRIORITY: return 4;
case ODP_ACTION_ATTR_POP_PRIORITY: return 0;
- case ODP_ACTION_ATTR_DROP_SPOOFED_ARP: return 0;
case ODP_ACTION_ATTR_UNSPEC:
case __ODP_ACTION_ATTR_MAX:
case ODP_ACTION_ATTR_OUTPUT:
ds_put_format(ds, "%"PRIu16, nl_attr_get_u32(a));
break;
- case ODP_ACTION_ATTR_CONTROLLER:
- ds_put_format(ds, "ctl(%"PRIu64")", nl_attr_get_u64(a));
+ case ODP_ACTION_ATTR_USERSPACE:
+ ds_put_format(ds, "userspace(%"PRIu64")", nl_attr_get_u64(a));
break;
case ODP_ACTION_ATTR_SET_TUNNEL:
ds_put_format(ds, "set_tunnel(%#"PRIx64")",
case ODP_ACTION_ATTR_POP_PRIORITY:
ds_put_cstr(ds, "pop_priority");
break;
- case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
- ds_put_cstr(ds, "drop_spoofed_arp");
- break;
default:
format_generic_odp_action(ds, a);
break;
case ODP_KEY_ATTR_ICMP: return sizeof(struct odp_key_icmp);
case ODP_KEY_ATTR_ICMPV6: return sizeof(struct odp_key_icmpv6);
case ODP_KEY_ATTR_ARP: return sizeof(struct odp_key_arp);
+ case ODP_KEY_ATTR_ND: return sizeof(struct odp_key_nd);
case ODP_KEY_ATTR_UNSPEC:
case __ODP_KEY_ATTR_MAX:
const struct odp_key_icmp *icmp_key;
const struct odp_key_icmpv6 *icmpv6_key;
const struct odp_key_arp *arp_key;
+ const struct odp_key_nd *nd_key;
if (nl_attr_get_size(a) != odp_flow_key_attr_len(nl_attr_type(a))) {
ds_put_format(ds, "bad length %zu, expected %d for: ",
switch (nl_attr_type(a)) {
case ODP_KEY_ATTR_TUN_ID:
- ds_put_format(ds, "tun_id(%#"PRIx64")", nl_attr_get_be64(a));
+ ds_put_format(ds, "tun_id(%#"PRIx64")", ntohll(nl_attr_get_be64(a)));
break;
case ODP_KEY_ATTR_IN_PORT:
ETH_ADDR_ARGS(arp_key->arp_tha));
break;
+ case ODP_KEY_ATTR_ND: {
+ char target[INET6_ADDRSTRLEN];
+
+ nd_key = nl_attr_get(a);
+ inet_ntop(AF_INET6, nd_key->nd_target, target, sizeof target);
+
+ ds_put_format(ds, "nd(target=%s", target);
+ if (!eth_addr_is_zero(nd_key->nd_sll)) {
+ ds_put_format(ds, ",sll="ETH_ADDR_FMT,
+ ETH_ADDR_ARGS(nd_key->nd_sll));
+ }
+ if (!eth_addr_is_zero(nd_key->nd_tll)) {
+ ds_put_format(ds, ",tll="ETH_ADDR_FMT,
+ ETH_ADDR_ARGS(nd_key->nd_tll));
+ }
+ ds_put_char(ds, ')');
+ break;
+ }
+
default:
format_generic_odp_key(a, ds);
break;
nl_msg_put_be64(buf, ODP_KEY_ATTR_TUN_ID, flow->tun_id);
}
- nl_msg_put_u32(buf, ODP_KEY_ATTR_IN_PORT, flow->in_port);
+ nl_msg_put_u32(buf, ODP_KEY_ATTR_IN_PORT,
+ ofp_port_to_odp_port(flow->in_port));
eth_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ETHERNET,
sizeof *eth_key);
ipv4_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_IPV4,
sizeof *ipv4_key);
+ memset(ipv4_key, 0, sizeof *ipv4_key);
ipv4_key->ipv4_src = flow->nw_src;
ipv4_key->ipv4_dst = flow->nw_dst;
ipv4_key->ipv4_proto = flow->nw_proto;
ipv6_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_IPV6,
sizeof *ipv6_key);
+ memset(ipv6_key, 0, sizeof *ipv6_key);
memcpy(ipv6_key->ipv6_src, &flow->ipv6_src, sizeof ipv6_key->ipv6_src);
memcpy(ipv6_key->ipv6_dst, &flow->ipv6_dst, sizeof ipv6_key->ipv6_dst);
ipv6_key->ipv6_proto = flow->nw_proto;
arp_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ARP,
sizeof *arp_key);
+ memset(arp_key, 0, sizeof *arp_key);
arp_key->arp_sip = flow->nw_src;
arp_key->arp_tip = flow->nw_dst;
arp_key->arp_op = htons(flow->nw_proto);
sizeof *icmpv6_key);
icmpv6_key->icmpv6_type = ntohs(flow->tp_src);
icmpv6_key->icmpv6_code = ntohs(flow->tp_dst);
+
+ if (icmpv6_key->icmpv6_type == ND_NEIGHBOR_SOLICIT
+ || icmpv6_key->icmpv6_type == ND_NEIGHBOR_ADVERT) {
+ struct odp_key_nd *nd_key;
+
+ nd_key = nl_msg_put_unspec_uninit(buf, ODP_KEY_ATTR_ND,
+ sizeof *nd_key);
+ memcpy(nd_key->nd_target, &flow->nd_target,
+ sizeof nd_key->nd_target);
+ memcpy(nd_key->nd_sll, flow->arp_sha, ETH_ADDR_LEN);
+ memcpy(nd_key->nd_tll, flow->arp_tha, ETH_ADDR_LEN);
+ }
}
}
}
const struct odp_key_icmp *icmp_key;
const struct odp_key_icmpv6 *icmpv6_key;
const struct odp_key_arp *arp_key;
+ const struct odp_key_nd *nd_key;
uint16_t type = nl_attr_type(nla);
int len = odp_flow_key_attr_len(type);
if (nl_attr_get_u32(nla) >= UINT16_MAX) {
return EINVAL;
}
- flow->in_port = nl_attr_get_u32(nla);
+ flow->in_port = odp_port_to_ofp_port(nl_attr_get_u32(nla));
break;
case TRANSITION(ODP_KEY_ATTR_IN_PORT, ODP_KEY_ATTR_ETHERNET):
memcpy(flow->arp_tha, arp_key->arp_tha, ETH_ADDR_LEN);
break;
+ case TRANSITION(ODP_KEY_ATTR_ICMPV6, ODP_KEY_ATTR_ND):
+ if (flow->tp_src != htons(ND_NEIGHBOR_SOLICIT)
+ && flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
+ return EINVAL;
+ }
+ nd_key = nl_attr_get(nla);
+ memcpy(&flow->nd_target, nd_key->nd_target, sizeof flow->nd_target);
+ memcpy(flow->arp_sha, nd_key->nd_sll, ETH_ADDR_LEN);
+ memcpy(flow->arp_tha, nd_key->nd_tll, ETH_ADDR_LEN);
+ break;
+
default:
if (type == ODP_KEY_ATTR_UNSPEC
|| prev_type == ODP_KEY_ATTR_UNSPEC) {
}
return 0;
+ case ODP_KEY_ATTR_ICMPV6:
+ if (flow->icmp_type == htons(ND_NEIGHBOR_SOLICIT)
+ || flow->icmp_type == htons(ND_NEIGHBOR_ADVERT)) {
+ return EINVAL;
+ }
+ return 0;
+
case ODP_KEY_ATTR_TCP:
case ODP_KEY_ATTR_UDP:
case ODP_KEY_ATTR_ICMP:
- case ODP_KEY_ATTR_ICMPV6:
case ODP_KEY_ATTR_ARP:
+ case ODP_KEY_ATTR_ND:
return 0;
case __ODP_KEY_ATTR_MAX: