.optional = true, },
[TCA_FLOWER_KEY_IP_TTL_MASK] = { .type = NL_A_U8,
.optional = true, },
+ [TCA_FLOWER_KEY_IP_TOS] = { .type = NL_A_U8,
+ .optional = true, },
+ [TCA_FLOWER_KEY_IP_TOS_MASK] = { .type = NL_A_U8,
+ .optional = true, },
[TCA_FLOWER_KEY_TCP_FLAGS] = { .type = NL_A_U16,
.optional = true, },
[TCA_FLOWER_KEY_TCP_FLAGS_MASK] = { .type = NL_A_U16,
.optional = true, },
+ [TCA_FLOWER_KEY_CVLAN_ID] = { .type = NL_A_U16, .optional = true, },
+ [TCA_FLOWER_KEY_CVLAN_PRIO] = { .type = NL_A_U8, .optional = true, },
+ [TCA_FLOWER_KEY_CVLAN_ETH_TYPE] = { .type = NL_A_U16, .optional = true, },
};
static void
static void
nl_parse_flower_vlan(struct nlattr **attrs, struct tc_flower *flower)
{
+ ovs_be16 encap_ethtype;
+
if (!eth_type_vlan(flower->key.eth_type)) {
return;
}
- flower->key.encap_eth_type =
+ flower->key.encap_eth_type[0] =
nl_attr_get_be16(attrs[TCA_FLOWER_KEY_ETH_TYPE]);
if (attrs[TCA_FLOWER_KEY_VLAN_ID]) {
- flower->key.vlan_id =
+ flower->key.vlan_id[0] =
nl_attr_get_u16(attrs[TCA_FLOWER_KEY_VLAN_ID]);
}
if (attrs[TCA_FLOWER_KEY_VLAN_PRIO]) {
- flower->key.vlan_prio =
+ flower->key.vlan_prio[0] =
nl_attr_get_u8(attrs[TCA_FLOWER_KEY_VLAN_PRIO]);
}
+
+ if (!attrs[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
+ return;
+ }
+
+ encap_ethtype = nl_attr_get_be16(attrs[TCA_FLOWER_KEY_VLAN_ETH_TYPE]);
+ if (!eth_type_vlan(encap_ethtype)) {
+ return;
+ }
+
+ flower->key.encap_eth_type[1] = flower->key.encap_eth_type[0];
+ flower->key.encap_eth_type[0] = encap_ethtype;
+
+ if (attrs[TCA_FLOWER_KEY_CVLAN_ID]) {
+ flower->key.vlan_id[1] =
+ nl_attr_get_u16(attrs[TCA_FLOWER_KEY_CVLAN_ID]);
+ }
+ if (attrs[TCA_FLOWER_KEY_CVLAN_PRIO]) {
+ flower->key.vlan_prio[1] =
+ nl_attr_get_u8(attrs[TCA_FLOWER_KEY_CVLAN_PRIO]);
+ }
}
static void
key->ip_ttl = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TTL]);
mask->ip_ttl = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TTL_MASK]);
}
+
+ if (attrs[TCA_FLOWER_KEY_IP_TOS_MASK]) {
+ key->ip_tos = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TOS]);
+ mask->ip_tos = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TOS_MASK]);
+ }
}
static enum tc_offloaded_state
struct nlattr *vlan_id = vlan_attrs[TCA_VLAN_PUSH_VLAN_ID];
struct nlattr *vlan_prio = vlan_attrs[TCA_VLAN_PUSH_VLAN_PRIORITY];
- action->vlan.vlan_push_tpid = nl_attr_get_u16(vlan_tpid);
+ action->vlan.vlan_push_tpid = nl_attr_get_be16(vlan_tpid);
action->vlan.vlan_push_id = nl_attr_get_u16(vlan_id);
action->vlan.vlan_push_prio = vlan_prio ? nl_attr_get_u8(vlan_prio) : 0;
action->type = TC_ACT_VLAN_PUSH;
}
static void
-nl_msg_put_act_push_vlan(struct ofpbuf *request, uint16_t tpid,
+nl_msg_put_act_push_vlan(struct ofpbuf *request, ovs_be16 tpid,
uint16_t vid, uint8_t prio)
{
size_t offset;
.v_action = TCA_VLAN_ACT_PUSH };
nl_msg_put_unspec(request, TCA_VLAN_PARMS, &parm, sizeof parm);
- nl_msg_put_u16(request, TCA_VLAN_PUSH_VLAN_PROTOCOL, tpid);
+ nl_msg_put_be16(request, TCA_VLAN_PUSH_VLAN_PROTOCOL, tpid);
nl_msg_put_u16(request, TCA_VLAN_PUSH_VLAN_ID, vid);
nl_msg_put_u8(request, TCA_VLAN_PUSH_VLAN_PRIORITY, prio);
}
uint16_t host_eth_type = ntohs(flower->key.eth_type);
bool is_vlan = eth_type_vlan(flower->key.eth_type);
+ bool is_qinq = is_vlan && eth_type_vlan(flower->key.encap_eth_type[0]);
int err;
/* need to parse acts first as some acts require changing the matching
}
if (is_vlan) {
- host_eth_type = ntohs(flower->key.encap_eth_type);
+ if (is_qinq) {
+ host_eth_type = ntohs(flower->key.encap_eth_type[1]);
+ } else {
+ host_eth_type = ntohs(flower->key.encap_eth_type[0]);
+ }
}
FLOWER_PUT_MASKED_VALUE(dst_mac, TCA_FLOWER_KEY_ETH_DST);
FLOWER_PUT_MASKED_VALUE(src_mac, TCA_FLOWER_KEY_ETH_SRC);
if (host_eth_type == ETH_P_IP || host_eth_type == ETH_P_IPV6) {
+ FLOWER_PUT_MASKED_VALUE(ip_ttl, TCA_FLOWER_KEY_IP_TTL);
+ FLOWER_PUT_MASKED_VALUE(ip_tos, TCA_FLOWER_KEY_IP_TOS);
+
if (flower->mask.ip_proto && flower->key.ip_proto) {
nl_msg_put_u8(request, TCA_FLOWER_KEY_IP_PROTO,
flower->key.ip_proto);
if (host_eth_type == ETH_P_IP) {
FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_src, TCA_FLOWER_KEY_IPV4_SRC);
FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_dst, TCA_FLOWER_KEY_IPV4_DST);
- FLOWER_PUT_MASKED_VALUE(ip_ttl, TCA_FLOWER_KEY_IP_TTL);
} else if (host_eth_type == ETH_P_IPV6) {
FLOWER_PUT_MASKED_VALUE(ipv6.ipv6_src, TCA_FLOWER_KEY_IPV6_SRC);
FLOWER_PUT_MASKED_VALUE(ipv6.ipv6_dst, TCA_FLOWER_KEY_IPV6_DST);
nl_msg_put_be16(request, TCA_FLOWER_KEY_ETH_TYPE, flower->key.eth_type);
if (is_vlan) {
- if (flower->key.vlan_id || flower->key.vlan_prio) {
+ if (flower->key.vlan_id[0] || flower->key.vlan_prio[0]) {
nl_msg_put_u16(request, TCA_FLOWER_KEY_VLAN_ID,
- flower->key.vlan_id);
+ flower->key.vlan_id[0]);
nl_msg_put_u8(request, TCA_FLOWER_KEY_VLAN_PRIO,
- flower->key.vlan_prio);
+ flower->key.vlan_prio[0]);
}
- if (flower->key.encap_eth_type) {
+ if (flower->key.encap_eth_type[0]) {
nl_msg_put_be16(request, TCA_FLOWER_KEY_VLAN_ETH_TYPE,
- flower->key.encap_eth_type);
+ flower->key.encap_eth_type[0]);
+ }
+
+ if (is_qinq) {
+ if (flower->key.vlan_id[1] || flower->key.vlan_prio[1]) {
+ nl_msg_put_u16(request, TCA_FLOWER_KEY_CVLAN_ID,
+ flower->key.vlan_id[1]);
+ nl_msg_put_u8(request, TCA_FLOWER_KEY_CVLAN_PRIO,
+ flower->key.vlan_prio[1]);
+ }
+ if (flower->key.encap_eth_type[1]) {
+ nl_msg_put_be16(request, TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+ flower->key.encap_eth_type[1]);
+ }
}
}