2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
21 #include "task_base.h"
22 #include "task_init.h"
27 #include "prox_assert.h"
31 struct task_base base;
35 static void init_task_untag(struct task_base *tbase, __attribute__((unused)) struct task_args *targ)
37 struct task_untag *task = (struct task_untag *)tbase;
38 task->etype = targ->etype;
41 static inline uint8_t handle_untag(struct task_untag *task, struct rte_mbuf *mbuf);
43 static int handle_untag_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
45 struct task_untag *task = (struct task_untag *)tbase;
46 uint8_t out[MAX_PKT_BURST];
49 prefetch_first(mbufs, n_pkts);
51 for (j = 0; j + PREFETCH_OFFSET < n_pkts; ++j) {
52 #ifdef PROX_PREFETCH_OFFSET
53 PREFETCH0(mbufs[j + PREFETCH_OFFSET]);
54 PREFETCH0(rte_pktmbuf_mtod(mbufs[j + PREFETCH_OFFSET - 1], void *));
56 out[j] = handle_untag(task, mbufs[j]);
58 #ifdef PROX_PREFETCH_OFFSET
59 PREFETCH0(rte_pktmbuf_mtod(mbufs[n_pkts - 1], void *));
60 for (; j < n_pkts; ++j) {
61 out[j] = handle_untag(task, mbufs[j]);
65 return task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
68 static inline uint8_t untag_mpls(struct rte_mbuf *mbuf, prox_rte_ether_hdr *peth)
70 prox_rte_ether_hdr *pneweth = (prox_rte_ether_hdr *)rte_pktmbuf_adj(mbuf, 4);
71 const struct mpls_hdr *mpls = (const struct mpls_hdr *)(peth + 1);
72 const prox_rte_ipv4_hdr *pip = (const prox_rte_ipv4_hdr *)(mpls + 1);
77 pneweth = (prox_rte_ether_hdr *)rte_pktmbuf_adj(mbuf, 4);
81 if ((pip->version_ihl >> 4) == 4) {
82 pneweth->ether_type = ETYPE_IPv4;
85 else if ((pip->version_ihl >> 4) == 6) {
86 pneweth->ether_type = ETYPE_IPv6;
90 plog_warn("Failed Decoding MPLS Packet - neither IPv4 neither IPv6: version %u\n", pip->version_ihl);
94 static uint8_t untag_qinq(struct rte_mbuf *mbuf, struct qinq_hdr *qinq)
96 if ((qinq->cvlan.eth_proto != ETYPE_VLAN)) {
97 plog_warn("Unexpected proto in QinQ = %#04x\n", qinq->cvlan.eth_proto);
101 rte_pktmbuf_adj(mbuf, sizeof(struct qinq_hdr) - sizeof(prox_rte_ether_hdr));
105 static inline uint8_t handle_untag(struct task_untag *task, struct rte_mbuf *mbuf)
107 prox_rte_ether_hdr *peth = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
108 const uint16_t etype = peth->ether_type;
110 if (etype != task->etype) {
111 plog_warn("Failed Removing %04x tag: ether_type = %#06x\n", task->etype, peth->ether_type);
117 /* MPLS Decapsulation */
118 return untag_mpls(mbuf, peth);
127 return untag_qinq(mbuf, (struct qinq_hdr *)peth);
129 plog_warn("Failed untagging header: ether_type = %#06x is not supported\n", peth->ether_type);
134 static struct task_init task_init_untag = {
136 .init = init_task_untag,
137 .handle = handle_untag_bulk,
138 .size = sizeof(struct task_untag)
141 __attribute__((constructor)) static void reg_task_untag(void)
143 reg_task(&task_init_untag);