pipeline: support QinQ PPPoE encapsulation
authorNemanja Marjanovic <nemanja.marjanovic@intel.com>
Mon, 21 Jan 2019 11:11:21 +0000 (11:11 +0000)
committerCristian Dumitrescu <cristian.dumitrescu@intel.com>
Fri, 29 Mar 2019 19:52:09 +0000 (20:52 +0100)
Add support of QinQ PPPoE packet encapsulation action.

Signed-off-by: Nemanja Marjanovic <nemanja.marjanovic@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
lib/librte_pipeline/rte_table_action.c
lib/librte_pipeline/rte_table_action.h

index 8a2bb13..ba8fd3f 100644 (file)
@@ -420,6 +420,7 @@ encap_valid(enum rte_table_action_encap_type encap)
        case RTE_TABLE_ACTION_ENCAP_MPLS:
        case RTE_TABLE_ACTION_ENCAP_PPPOE:
        case RTE_TABLE_ACTION_ENCAP_VXLAN:
+       case RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
                return 1;
        default:
                return 0;
@@ -520,6 +521,13 @@ struct encap_vxlan_ipv6_vlan_data {
        struct vxlan_hdr vxlan;
 } __attribute__((__packed__));
 
+struct encap_qinq_pppoe_data {
+       struct ether_hdr ether;
+       struct vlan_hdr svlan;
+       struct vlan_hdr cvlan;
+       struct pppoe_ppp_hdr pppoe_ppp;
+} __attribute__((__packed__));
+
 static size_t
 encap_data_size(struct rte_table_action_encap_config *encap)
 {
@@ -551,6 +559,9 @@ encap_data_size(struct rte_table_action_encap_config *encap)
                        else
                                return sizeof(struct encap_vxlan_ipv6_data);
 
+       case 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
+                       return sizeof(struct encap_qinq_pppoe_data);
+
        default:
                return 0;
        }
@@ -587,6 +598,9 @@ encap_apply_check(struct rte_table_action_encap_params *p,
        case RTE_TABLE_ACTION_ENCAP_VXLAN:
                return 0;
 
+       case RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
+               return 0;
+
        default:
                return -EINVAL;
        }
@@ -664,6 +678,38 @@ encap_qinq_apply(void *data,
        return 0;
 }
 
+static int
+encap_qinq_pppoe_apply(void *data,
+       struct rte_table_action_encap_params *p)
+{
+       struct encap_qinq_pppoe_data *d = data;
+
+       /* Ethernet */
+       ether_addr_copy(&p->qinq.ether.da, &d->ether.d_addr);
+       ether_addr_copy(&p->qinq.ether.sa, &d->ether.s_addr);
+       d->ether.ether_type = rte_htons(ETHER_TYPE_VLAN);
+
+       /* SVLAN */
+       d->svlan.vlan_tci = rte_htons(VLAN(p->qinq.svlan.pcp,
+               p->qinq.svlan.dei,
+               p->qinq.svlan.vid));
+       d->svlan.eth_proto = rte_htons(ETHER_TYPE_VLAN);
+
+       /* CVLAN */
+       d->cvlan.vlan_tci = rte_htons(VLAN(p->qinq.cvlan.pcp,
+               p->qinq.cvlan.dei,
+               p->qinq.cvlan.vid));
+       d->cvlan.eth_proto = rte_htons(ETHER_TYPE_PPPOE_SESSION);
+
+       /* PPPoE and PPP*/
+       d->pppoe_ppp.ver_type_code = rte_htons(0x1100);
+       d->pppoe_ppp.session_id = rte_htons(p->qinq_pppoe.pppoe.session_id);
+       d->pppoe_ppp.length = 0; /* not pre-computed */
+       d->pppoe_ppp.protocol = rte_htons(PPP_PROTOCOL_IP);
+
+       return 0;
+}
+
 static int
 encap_mpls_apply(void *data,
        struct rte_table_action_encap_params *p)
@@ -909,6 +955,9 @@ encap_apply(void *data,
        case RTE_TABLE_ACTION_ENCAP_VXLAN:
                return encap_vxlan_apply(data, p, cfg);
 
+       case RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
+               return encap_qinq_pppoe_apply(data, p);
+
        default:
                return -EINVAL;
        }
@@ -1107,6 +1156,18 @@ pkt_work_encap(struct rte_mbuf *mbuf,
                break;
        }
 
+       case 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
+       {
+               struct encap_qinq_pppoe_data *qinq_pppoe =
+                       encap(ip, data, sizeof(struct encap_qinq_pppoe_data));
+               qinq_pppoe->pppoe_ppp.length = rte_htons(total_length + 2);
+               mbuf->data_off = ip_offset - (sizeof(struct rte_mbuf) +
+                       sizeof(struct encap_qinq_pppoe_data));
+               mbuf->pkt_len = mbuf->data_len = total_length +
+                       sizeof(struct encap_qinq_pppoe_data);
+               break;
+       }
+
        case 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN:
        {
                if (cfg->vxlan.ip_version)
index c960612..53d16af 100644 (file)
@@ -380,6 +380,9 @@ enum rte_table_action_encap_type {
         * Ether -> { Ether | VLAN | IP | UDP | VXLAN | Ether }
         */
        RTE_TABLE_ACTION_ENCAP_VXLAN,
+
+       /** IP -> { Ether | S-VLAN | C-VLAN | PPPoE | PPP | IP } */
+       RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE,
 };
 
 /** Pre-computed Ethernet header fields for encapsulation action. */
@@ -529,6 +532,16 @@ struct rte_table_action_encap_config {
        };
 };
 
+/** QinQ_PPPoE encap paramaeters. */
+struct rte_table_encap_ether_qinq_pppoe {
+
+       /** Only valid when *type* is set to QinQ. */
+       struct rte_table_action_ether_hdr ether;
+       struct rte_table_action_vlan_hdr svlan; /**< Service VLAN header. */
+       struct rte_table_action_vlan_hdr cvlan; /**< Customer VLAN header. */
+       struct rte_table_action_pppoe_hdr pppoe; /**< PPPoE/PPP headers. */
+};
+
 /** Encap action parameters (per table rule). */
 struct rte_table_action_encap_params {
        /** Encapsulation type. */
@@ -553,6 +566,9 @@ struct rte_table_action_encap_params {
 
                /** Only valid when *type* is set to VXLAN. */
                struct rte_table_action_encap_vxlan_params vxlan;
+
+               /** Only valid when *type* is set to QinQ_PPPoE. */
+               struct rte_table_encap_ether_qinq_pppoe qinq_pppoe;
        };
 };