aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/pktio/pktio_common.c
blob: 8a01477f5c50b04cc820d5dd300b854e60ee9964 (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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* Copyright (c) 2013, Linaro Limited
 * Copyright (c) 2013, Nokia Solutions and Networks
 * All rights reserved.
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 */

#include <odp_packet_io_internal.h>
#include <odp_classification_internal.h>
#include <errno.h>

/**
 * Classify packet, copy it in a odp_packet_t and enqueue to the right queue
 *
 * pktio_entry	pktio where it arrived
 * base		packet data
 * buf_len	packet length
 *
 * Return values:
 * 0 on success, packet is consumed
 * -ENOENT CoS dropped the packet
 * -EFAULT Bug
 * -EINVAL Config error
 * -ENOMEM Target CoS pool exhausted
 *
 * Note: *base is not released, only pkt if there is an error
 *
 */
int _odp_packet_cls_enq(pktio_entry_t *pktio_entry,
			const uint8_t *base, uint16_t buf_len, odp_time_t *ts)
{
	cos_t *cos;
	odp_packet_t pkt;
	odp_packet_hdr_t *pkt_hdr;
	odp_packet_hdr_t src_pkt_hdr;
	int ret;
	odp_pool_t pool;

	packet_parse_reset(&src_pkt_hdr);

	_odp_cls_parse(&src_pkt_hdr, base);
	cos = pktio_select_cos(pktio_entry, base, &src_pkt_hdr);

	/* if No CoS found then drop the packet */
	if (cos == NULL)
		return -EINVAL;

	if (cos->s.queue == NULL || cos->s.pool == NULL)
		return -EFAULT;

	pool = cos->s.pool->s.pool_hdl;

	pkt = odp_packet_alloc(pool, buf_len);
	if (odp_unlikely(pkt == ODP_PACKET_INVALID))
		return -ENOMEM;
	pkt_hdr = odp_packet_hdr(pkt);

	copy_packet_parser_metadata(&src_pkt_hdr, pkt_hdr);
	pkt_hdr->input = pktio_entry->s.handle;

	if (odp_packet_copy_from_mem(pkt, 0, buf_len, base) != 0) {
		odp_packet_free(pkt);
		return -EFAULT;
	}

	packet_set_ts(pkt_hdr, ts);

	/* Parse and set packet header data */
	odp_packet_pull_tail(pkt, odp_packet_len(pkt) - buf_len);
	ret = queue_enq(cos->s.queue, odp_buf_to_hdr((odp_buffer_t)pkt), 0);
	if (ret < 0) {
		odp_packet_free(pkt);
		return -EFAULT;
	}

	return 0;
}

int sock_stats_reset_fd(pktio_entry_t *pktio_entry, int fd)
{
	int err = 0;
	odp_pktio_stats_t cur_stats;

	if (pktio_entry->s.stats_type == STATS_UNSUPPORTED) {
		memset(&pktio_entry->s.stats, 0,
		       sizeof(odp_pktio_stats_t));
		return 0;
	}

	memset(&cur_stats, 0, sizeof(odp_pktio_stats_t));

	if (pktio_entry->s.stats_type == STATS_ETHTOOL) {
		(void)ethtool_stats_get_fd(fd,
					   pktio_entry->s.name,
					   &cur_stats);
	} else if (pktio_entry->s.stats_type == STATS_SYSFS) {
		err = sysfs_stats(pktio_entry, &cur_stats);
		if (err != 0)
			ODP_ERR("stats error\n");
	}

	if (err == 0)
		memcpy(&pktio_entry->s.stats, &cur_stats,
		       sizeof(odp_pktio_stats_t));

	return err;
}

int sock_stats_fd(pktio_entry_t *pktio_entry,
		  odp_pktio_stats_t *stats,
		  int fd)
{
	odp_pktio_stats_t cur_stats;
	int ret = 0;

	if (pktio_entry->s.stats_type == STATS_UNSUPPORTED)
		return 0;

	memset(&cur_stats, 0, sizeof(odp_pktio_stats_t));
	if (pktio_entry->s.stats_type == STATS_ETHTOOL) {
		(void)ethtool_stats_get_fd(fd,
					   pktio_entry->s.name,
					   &cur_stats);
	} else if (pktio_entry->s.stats_type == STATS_SYSFS) {
		sysfs_stats(pktio_entry, &cur_stats);
	}

	stats->in_octets = cur_stats.in_octets -
				pktio_entry->s.stats.in_octets;
	stats->in_ucast_pkts = cur_stats.in_ucast_pkts -
				pktio_entry->s.stats.in_ucast_pkts;
	stats->in_discards = cur_stats.in_discards -
				pktio_entry->s.stats.in_discards;
	stats->in_errors = cur_stats.in_errors -
				pktio_entry->s.stats.in_errors;
	stats->in_unknown_protos = cur_stats.in_unknown_protos -
				pktio_entry->s.stats.in_unknown_protos;

	stats->out_octets = cur_stats.out_octets -
				pktio_entry->s.stats.out_octets;
	stats->out_ucast_pkts = cur_stats.out_ucast_pkts -
				pktio_entry->s.stats.out_ucast_pkts;
	stats->out_discards = cur_stats.out_discards -
				pktio_entry->s.stats.out_discards;
	stats->out_errors = cur_stats.out_errors -
				pktio_entry->s.stats.out_errors;

	return ret;
}