summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/stats_cons.h
blob: ba51f49f8c84527316719176e55df661d4a83d50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
// Copyright (c) 2010-2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#ifndef _STATS_CONS_H_
#define _STATS_CONS_H_

#define STATS_CONS_F_TASKS      0x01
#define STATS_CONS_F_LCORE      0x02
#define STATS_CONS_F_PORTS      0x04
#define STATS_CONS_F_MEMPOOLS   0x08
#define STATS_CONS_F_RINGS      0x10
#define STATS_CONS_F_LATENCY    0x20
#define STATS_CONS_F_L4GEN      0x40
#define STATS_CONS_F_GLOBAL     0x80
#define STATS_CONS_F_PRIO_TASKS 0x100
#define STATS_CONS_F_ALL        0x1ff

struct stats_cons {
	void (*init)(void);
	void (*notify)(void);
	void (*refresh)(void); /* Only called if not NULL, used to signal lsc or core stop/start */
	void (*finish)(void);
	uint16_t flags;
};

#endif /* _STATS_CONS_H_ */
#0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
// Copyright (c) 2010-2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include <rte_ethdev.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <rte_udp.h>

#include "vxlangpe_nsh.h"
#include "task_base.h"
#include "tx_pkt.h"
#include "task_init.h"
#include "thread_generic.h"
#include "prefetch.h"
#include "log.h"

#define VXLAN_GPE_HDR_SZ sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + sizeof(struct vxlan_gpe_hdr) + sizeof(struct nsh_hdr)
#define ETHER_NSH_TYPE 0x4F89 /* 0x894F in little endian */
#define VXLAN_GPE_NSH_TYPE 0xB612 /* 4790 in little endian */
#define VXLAN_GPE_NP 0x4

uint16_t decap_nsh_packets(struct rte_mbuf **mbufs, uint16_t n_pkts);
uint16_t encap_nsh_packets(struct rte_mbuf **mbufs, uint16_t n_pkts);

struct task_decap_nsh {
	struct task_base base;
};

struct task_encap_nsh {
	struct task_base base;
};

static void init_task_decap_nsh(__attribute__((unused)) struct task_base *tbase,
			     __attribute__((unused)) struct task_args *targ)
{
	return;
}

static inline uint8_t handle_decap_nsh(__attribute__((unused)) struct task_decap_nsh *task, struct rte_mbuf *mbuf)
{
	struct ether_hdr *eth_hdr = NULL;
	struct udp_hdr *udp_hdr = NULL;
	struct vxlan_gpe_hdr *vxlan_gpe_hdr = NULL;
	uint16_t hdr_len;

	eth_hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
	if (eth_hdr->ether_type == ETHER_NSH_TYPE) {
		/* "decapsulate" Ethernet + NSH header by moving packet pointer */
		hdr_len = sizeof(struct ether_hdr) + sizeof(struct nsh_hdr);

		mbuf->data_len = (uint16_t)(mbuf->data_len - hdr_len);
		mbuf->data_off += hdr_len;
		mbuf->pkt_len = (uint32_t)(mbuf->pkt_len - hdr_len);
		/* save length of header in reserved 16bits of rte_mbuf */
		mbuf->udata64 = hdr_len;
	}
	else {
		if (mbuf->data_len < VXLAN_GPE_HDR_SZ) {
			mbuf->udata64 = 0;
			return 0;
		}

		/* check the UDP destination port */
		udp_hdr = (struct udp_hdr *)(((unsigned char *)eth_hdr) + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr));
		if (udp_hdr->dst_port != VXLAN_GPE_NSH_TYPE) {
			mbuf->udata64 = 0;
			return 0;
		}

		/* check the Next Protocol field in VxLAN-GPE header */
		vxlan_gpe_hdr = (struct vxlan_gpe_hdr *)(((unsigned char *)eth_hdr) + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr));
		if (vxlan_gpe_hdr->next_proto != VXLAN_GPE_NP) {
			mbuf->udata64 = 0;
			return 0;
		}

		/* "decapsulate" VxLAN-GPE + NSH header by moving packet pointer */
		hdr_len = VXLAN_GPE_HDR_SZ;

		mbuf->data_len = (uint16_t)(mbuf->data_len - hdr_len);
		mbuf->data_off += hdr_len;
		mbuf->pkt_len  = (uint32_t)(mbuf->pkt_len - hdr_len);
		/* save length of header in reserved 16bits of rte_mbuf */
		mbuf->udata64 = hdr_len;
	}

	return 0;
}

static int handle_decap_nsh_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
{
	struct task_decap_nsh *task = (struct task_decap_nsh *)tbase;
	uint8_t out[MAX_PKT_BURST];
	uint16_t j;

	prefetch_first(mbufs, n_pkts);
	for (j = 0; j + PREFETCH_OFFSET < n_pkts; ++j) {
#ifdef PROX_PREFETCH_OFFSET
		PREFETCH0(mbufs[j + PREFETCH_OFFSET]);
		PREFETCH0(rte_pktmbuf_mtod(mbufs[j + PREFETCH_OFFSET - 1], void *));
#endif
		out[j] = handle_decap_nsh(task, mbufs[j]);
	}
#ifdef PROX_PREFETCH_OFFSET
	PREFETCH0(rte_pktmbuf_mtod(mbufs[n_pkts - 1], void *));
	for (; j < n_pkts; ++j) {
		out[j] = handle_decap_nsh(task, mbufs[j]);
	}
#endif
	return task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
}

static void init_task_encap_nsh(__attribute__((unused)) struct task_base *tbase,
			      __attribute__((unused)) struct task_args *targ)
{
	return;
}

static inline uint8_t handle_encap_nsh(__attribute__((unused)) struct task_encap_nsh *task, struct rte_mbuf *mbuf)
{
	struct ether_hdr *eth_hdr = NULL;
	struct nsh_hdr *nsh_hdr = NULL;
	struct udp_hdr *udp_hdr = NULL;
	struct vxlan_gpe_hdr *vxlan_gpe_hdr = NULL;
	uint16_t hdr_len;

	if (mbuf == NULL)
		return 0;
	if (mbuf->udata64 == 0)
		return 0;

	/* use header length saved in reserved 16bits of rte_mbuf to
	   "encapsulate" transport + NSH header by moving packet pointer */
	mbuf->data_len = (uint16_t)(mbuf->data_len + mbuf->udata64);
	mbuf->data_off -= mbuf->udata64;
	mbuf->pkt_len  = (uint32_t)(mbuf->pkt_len + mbuf->udata64);

	eth_hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
	if (eth_hdr->ether_type == ETHER_NSH_TYPE) {
		nsh_hdr = (struct nsh_hdr *) (((unsigned char *)eth_hdr) + sizeof(struct ether_hdr));

		/* decrement Service Index in NSH header */
		if (nsh_hdr->sf_index > 0)
			nsh_hdr->sf_index -= 1;
	}
	else {
		/* "encapsulate" VxLAN-GPE + NSH header by moving packet pointer */
		if (mbuf->data_len < VXLAN_GPE_HDR_SZ)
			return 0;

		/* check the UDP destination port */
		udp_hdr = (struct udp_hdr *)(((unsigned char *)eth_hdr) + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr));
		if (udp_hdr->dst_port != VXLAN_GPE_NSH_TYPE)
			return 0;

		/* check the Next Protocol field in VxLAN-GPE header */
		vxlan_gpe_hdr = (struct vxlan_gpe_hdr *)(((unsigned char *)eth_hdr) + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr));
		if (vxlan_gpe_hdr->next_proto != VXLAN_GPE_NP)
			return 0;

		/* decrement Service Index in NSH header */
		nsh_hdr = (struct nsh_hdr *)(((unsigned char *)vxlan_gpe_hdr) + sizeof(struct vxlan_gpe_hdr));
		if (nsh_hdr->sf_index > 0)
			nsh_hdr->sf_index -= 1;
	}

	return 0;
}

static int handle_encap_nsh_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
{
	struct task_encap_nsh *task = (struct task_encap_nsh *)tbase;
	uint8_t out[MAX_PKT_BURST];
	uint16_t j;

	prefetch_first(mbufs, n_pkts);
	for (j = 0; j + PREFETCH_OFFSET < n_pkts; ++j) {
#ifdef PROX_PREFETCH_OFFSET
		PREFETCH0(mbufs[j + PREFETCH_OFFSET]);
		PREFETCH0(rte_pktmbuf_mtod(mbufs[j + PREFETCH_OFFSET - 1], void *));
#endif
		out[j] = handle_encap_nsh(task, mbufs[j]);
	}
#ifdef PROX_PREFETCH_OFFSET
	PREFETCH0(rte_pktmbuf_mtod(mbufs[n_pkts - 1], void *));
	for (; j < n_pkts; ++j) {
		out[j] = handle_encap_nsh(task, mbufs[j]);
	}
#endif
	return task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
}

static struct task_init task_init_decap_nsh = {
	.mode_str = "decapnsh",
	.init = init_task_decap_nsh,
	.handle = handle_decap_nsh_bulk,
	.thread_x = thread_generic,
	.size = sizeof(struct task_decap_nsh)
};

static struct task_init task_init_encap_nsh = {
	.mode_str = "encapnsh",
	.init = init_task_encap_nsh,
	.handle = handle_encap_nsh_bulk,
	.size = sizeof(struct task_encap_nsh)
};

__attribute__((constructor)) static void reg_task_nshtag(void)
{
	reg_task(&task_init_decap_nsh);
	reg_task(&task_init_encap_nsh);
}