]> git.proxmox.com Git - ovs.git/blobdiff - lib/tc.c
lib/tc: Support matching on ip tos
[ovs.git] / lib / tc.c
index 503039959ca9c72fd7c07e9383c3de4706f35a9e..ec7efff69cad71c2cc6a1eea06c397015be54114 100644 (file)
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -302,10 +302,17 @@ static const struct nl_policy tca_flower_policy[] = {
                                 .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
@@ -332,21 +339,44 @@ nl_parse_flower_eth(struct nlattr **attrs, struct tc_flower *flower)
 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
@@ -471,6 +501,11 @@ nl_parse_flower_ip(struct nlattr **attrs, struct tc_flower *flower) {
         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
@@ -788,7 +823,7 @@ nl_parse_act_vlan(struct nlattr *options, struct tc_flower *flower)
         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;
@@ -1160,7 +1195,7 @@ nl_msg_put_act_pedit(struct ofpbuf *request, struct tc_pedit *parm,
 }
 
 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;
@@ -1172,7 +1207,7 @@ nl_msg_put_act_push_vlan(struct ofpbuf *request, uint16_t tpid,
                                 .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);
     }
@@ -1577,6 +1612,7 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
 
     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
@@ -1587,13 +1623,20 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
     }
 
     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);
@@ -1622,7 +1665,6 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
     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);
@@ -1631,15 +1673,28 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
     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]);
+            }
         }
     }