uint64_t present_attrs;
size_t left;
+ BUILD_ASSERT(OVS_KEY_ATTR_MAX < CHAR_BIT * sizeof present_attrs);
present_attrs = 0;
*out_of_range_attrp = 0;
NL_ATTR_FOR_EACH (nla, left, key, key_len) {
return false;
}
- if (type >= CHAR_BIT * sizeof present_attrs) {
+ if (type > OVS_KEY_ATTR_MAX) {
*out_of_range_attrp = type;
} else {
if (present_attrs & (UINT64_C(1) << type)) {
const struct nlattr *key, size_t key_len)
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
- ovs_be16 dl_type;
- /* Parse MPLS label stack entry */
if (eth_type_mpls(flow->dl_type)) {
- /* Calculate fitness of outer attributes. */
expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_MPLS);
- /* Get the MPLS LSE value. */
if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_MPLS))) {
return ODP_FIT_TOO_LITTLE;
}
flow->mpls_lse = nl_attr_get_be32(attrs[OVS_KEY_ATTR_MPLS]);
flow->mpls_depth++;
-
- if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4)) {
- flow->encap_dl_type = htons(ETH_TYPE_IP);
- } else if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV6)) {
- flow->encap_dl_type = htons(ETH_TYPE_IPV6);
- } else if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ARP)) {
- flow->encap_dl_type = htons(ETH_TYPE_ARP);
- }
- }
-
- dl_type = flow_innermost_dl_type(flow);
-
- if (dl_type == htons(ETH_TYPE_IP)) {
+ } else if (flow->dl_type == htons(ETH_TYPE_IP)) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV4;
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV4)) {
const struct ovs_key_ipv4 *ipv4_key;
return ODP_FIT_ERROR;
}
}
- } else if (dl_type == htons(ETH_TYPE_IPV6)) {
+ } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IPV6;
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IPV6)) {
const struct ovs_key_ipv6 *ipv6_key;
return ODP_FIT_ERROR;
}
}
- } else if (dl_type == htons(ETH_TYPE_ARP) ||
- dl_type == htons(ETH_TYPE_RARP)) {
+ } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
+ flow->dl_type == htons(ETH_TYPE_RARP)) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ARP;
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ARP)) {
const struct ovs_key_arp *arp_key;
}
if (flow->nw_proto == IPPROTO_TCP
- && (dl_type == htons(ETH_TYPE_IP) ||
- dl_type == htons(ETH_TYPE_IPV6))
+ && (flow->dl_type == htons(ETH_TYPE_IP) ||
+ flow->dl_type == htons(ETH_TYPE_IPV6))
&& !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP;
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TCP)) {
flow->tp_dst = tcp_key->tcp_dst;
}
} else if (flow->nw_proto == IPPROTO_UDP
- && (dl_type == htons(ETH_TYPE_IP) ||
- dl_type == htons(ETH_TYPE_IPV6))
+ && (flow->dl_type == htons(ETH_TYPE_IP) ||
+ flow->dl_type == htons(ETH_TYPE_IPV6))
&& !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_UDP;
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_UDP)) {
flow->tp_dst = udp_key->udp_dst;
}
} else if (flow->nw_proto == IPPROTO_ICMP
- && dl_type == htons(ETH_TYPE_IP)
+ && flow->dl_type == htons(ETH_TYPE_IP)
&& !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMP;
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ICMP)) {
flow->tp_dst = htons(icmp_key->icmp_code);
}
} else if (flow->nw_proto == IPPROTO_ICMPV6
- && dl_type == htons(ETH_TYPE_IPV6)
+ && flow->dl_type == htons(ETH_TYPE_IPV6)
&& !(flow->nw_frag & FLOW_NW_FRAG_LATER)) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ICMPV6;
if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ICMPV6)) {
commit_set_nw_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
- ovs_be16 dl_type = flow_innermost_dl_type(flow);
-
/* Check if flow really have an IP header. */
if (!flow->nw_proto) {
return;
}
- if (dl_type == htons(ETH_TYPE_IP)) {
+ if (base->dl_type == htons(ETH_TYPE_IP)) {
commit_set_ipv4_action(flow, base, odp_actions);
- } else if (dl_type == htons(ETH_TYPE_IPV6)) {
+ } else if (base->dl_type == htons(ETH_TYPE_IPV6)) {
commit_set_ipv6_action(flow, base, odp_actions);
}
}
commit_set_port_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
- if (!base->tp_src && !base->tp_dst) {
+ if (!is_ip_any(base) || (!base->tp_src && !base->tp_dst)) {
return;
}
{
commit_set_ether_addr_action(flow, base, odp_actions);
commit_vlan_action(flow, base, odp_actions);
- commit_mpls_action(flow, base, odp_actions);
commit_set_nw_action(flow, base, odp_actions);
commit_set_port_action(flow, base, odp_actions);
+ /* Commiting MPLS actions should occur after committing nw and port
+ * actions. This is because committing MPLS actions may alter a packet so
+ * that it is no longer IP and thus nw and port actions are no longer valid.
+ */
+ commit_mpls_action(flow, base, odp_actions);
commit_set_priority_action(flow, base, odp_actions);
commit_set_skb_mark_action(flow, base, odp_actions);
}