@@ -352,6 +352,8 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_ZONE, /* u16 connection tracking zone. */
OVS_KEY_ATTR_CT_MARK, /* u32 connection tracking mark */
OVS_KEY_ATTR_CT_LABELS, /* 16-octet connection tracking labels */
+ OVS_KEY_ATTR_PACKET_ETHERTYPE, /* be16 Ethernet type for packet
+ * execution. */
#ifdef __KERNEL__
/* Only used within kernel data path. */
@@ -932,6 +932,10 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
if (!ovs_u128_is_zero(&flow->ct_label)) {
match_set_ct_label(flow_metadata, flow->ct_label);
}
+
+ if (flow->base_layer != LAYER_2) {
+ match_set_base_layer(flow_metadata, flow->base_layer);
+ }
}
const char *ct_state_to_string(uint32_t state)
@@ -1007,6 +1007,8 @@ pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow)
md->ct_zone = flow->ct_zone;
md->ct_mark = flow->ct_mark;
md->ct_label = flow->ct_label;
+ md->base_layer = flow->base_layer;
+ md->packet_ethertype = flow->dl_type;
}
static inline bool is_ip_any(const struct flow *flow)
@@ -367,6 +367,13 @@ match_set_ct_label_masked(struct match *match, ovs_u128 value, ovs_u128 mask)
}
void
+match_set_base_layer(struct match *match, uint8_t base_layer)
+{
+ match->flow.base_layer = base_layer;
+ match->wc.masks.base_layer = UINT8_MAX;
+}
+
+void
match_set_dl_type(struct match *match, ovs_be16 dl_type)
{
match->wc.masks.dl_type = OVS_BE16_MAX;
@@ -96,6 +96,7 @@ void match_set_ct_mark(struct match *, uint32_t ct_mark);
void match_set_ct_mark_masked(struct match *, uint32_t ct_mark, uint32_t mask);
void match_set_ct_label(struct match *, ovs_u128 ct_label);
void match_set_ct_label_masked(struct match *, ovs_u128 ct_label, ovs_u128 mask);
+void match_set_base_layer(struct match *, uint8_t base_layer);
void match_set_skb_priority(struct match *, uint32_t skb_priority);
void match_set_dl_type(struct match *, ovs_be16);
void match_set_dl_src(struct match *, const struct eth_addr );
@@ -328,6 +328,10 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
md->recirc_id = nl_attr_get_u32(a);
break;
+ case OVS_KEY_ATTR_PACKET_ETHERTYPE:
+ md->packet_ethertype = nl_attr_get_be16(a);
+ break;
+
case OVS_KEY_ATTR_UNSPEC:
case OVS_KEY_ATTR_ENCAP:
case OVS_KEY_ATTR_ETHERTYPE:
@@ -424,6 +428,11 @@ odp_execute_masked_set_action(struct dp_packet *packet,
| (md->recirc_id & ~*get_mask(a, uint32_t));
break;
+ case OVS_KEY_ATTR_PACKET_ETHERTYPE:
+ md->packet_ethertype = nl_attr_get_be16(a)
+ | (md->packet_ethertype & ~*get_mask(a, ovs_be16));
+ break;
+
case OVS_KEY_ATTR_TUNNEL: /* Masked data not supported for tunnel. */
case OVS_KEY_ATTR_UNSPEC:
case OVS_KEY_ATTR_CT_STATE:
@@ -165,6 +165,7 @@ ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize)
case OVS_KEY_ATTR_MPLS: return "mpls";
case OVS_KEY_ATTR_DP_HASH: return "dp_hash";
case OVS_KEY_ATTR_RECIRC_ID: return "recirc_id";
+ case OVS_KEY_ATTR_PACKET_ETHERTYPE: return "pkt_eth";
case __OVS_KEY_ATTR_MAX:
default:
@@ -1827,6 +1828,7 @@ static const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] =
[OVS_KEY_ATTR_CT_ZONE] = { .len = 2 },
[OVS_KEY_ATTR_CT_MARK] = { .len = 4 },
[OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
+ [OVS_KEY_ATTR_PACKET_ETHERTYPE] = { .len = 2 },
};
/* Returns the correct length of the payload for a flow key attribute of the
@@ -2848,6 +2850,7 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma,
break;
}
case OVS_KEY_ATTR_ETHERTYPE:
+ case OVS_KEY_ATTR_PACKET_ETHERTYPE:
ds_put_format(ds, "0x%04"PRIx16, ntohs(nl_attr_get_be16(a)));
if (!is_exact) {
ds_put_format(ds, "/0x%04"PRIx16, ntohs(nl_attr_get_be16(ma)));
@@ -4484,6 +4487,13 @@ odp_key_from_pkt_metadata(struct ofpbuf *buf, const struct pkt_metadata *md)
if (md->in_port.odp_port != ODPP_NONE) {
nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, md->in_port.odp_port);
}
+
+ if (md->base_layer == LAYER_2) {
+ nl_msg_put_be16(buf, OVS_KEY_ATTR_PACKET_ETHERTYPE, htons(0));
+ } else {
+ nl_msg_put_be16(buf, OVS_KEY_ATTR_PACKET_ETHERTYPE,
+ md->packet_ethertype);
+ }
}
/* Generate packet metadata from the given ODP flow key. */
@@ -4495,10 +4505,13 @@ odp_key_to_pkt_metadata(const struct nlattr *key, size_t key_len,
size_t left;
uint32_t wanted_attrs = 1u << OVS_KEY_ATTR_PRIORITY |
1u << OVS_KEY_ATTR_SKB_MARK | 1u << OVS_KEY_ATTR_TUNNEL |
- 1u << OVS_KEY_ATTR_IN_PORT;
+ 1u << OVS_KEY_ATTR_IN_PORT | 1u << OVS_KEY_ATTR_ETHERNET |
+ 1u << OVS_KEY_ATTR_IPV4 | 1u << OVS_KEY_ATTR_IPV6;
pkt_metadata_init(md, ODPP_NONE);
+ md->base_layer = LAYER_3;
+
NL_ATTR_FOR_EACH (nla, left, key, key_len) {
uint16_t type = nl_attr_type(nla);
size_t len = nl_attr_get_size(nla);
@@ -4560,6 +4573,18 @@ odp_key_to_pkt_metadata(const struct nlattr *key, size_t key_len,
md->in_port.odp_port = nl_attr_get_odp_port(nla);
wanted_attrs &= ~(1u << OVS_KEY_ATTR_IN_PORT);
break;
+ case OVS_KEY_ATTR_ETHERNET:
+ md->base_layer = LAYER_2;
+ wanted_attrs &= ~(1u << OVS_KEY_ATTR_ETHERNET);
+ break;
+ case OVS_KEY_ATTR_IPV4:
+ md->packet_ethertype = htons(ETH_TYPE_IP);
+ wanted_attrs &= ~(1u << OVS_KEY_ATTR_IPV4);
+ break;
+ case OVS_KEY_ATTR_IPV6:
+ md->packet_ethertype = htons(ETH_TYPE_IPV6);
+ wanted_attrs &= ~(1u << OVS_KEY_ATTR_IPV6);
+ break;
default:
break;
}
@@ -145,6 +145,8 @@ struct pkt_metadata {
uint32_t ct_mark; /* Connection mark. */
ovs_u128 ct_label; /* Connection label. */
union flow_in_port in_port; /* Input port. */
+ ovs_be16 packet_ethertype; /* Ethertype of the packet */
+ uint8_t base_layer; /* Packet starts at this layer */
struct flow_tnl tunnel; /* Encapsulating tunnel parameters. Note that
* if 'ip_dst' == 0, the rest of the fields may
* be uninitialized. */
@@ -974,6 +974,7 @@ sflow_read_set_action(const struct nlattr *attr,
case OVS_KEY_ATTR_IN_PORT:
case OVS_KEY_ATTR_ETHERNET:
case OVS_KEY_ATTR_VLAN:
+ case OVS_KEY_ATTR_PACKET_ETHERTYPE:
break;
case OVS_KEY_ATTR_MPLS: {