1a9643ea8Slogwang /*
2*2317ada5Sfengbojiang * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
3a9643ea8Slogwang * All rights reserved.
4a9643ea8Slogwang *
5a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without
6a9643ea8Slogwang * modification, are permitted provided that the following conditions are met:
7a9643ea8Slogwang *
8a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright notice, this
9a9643ea8Slogwang * list of conditions and the following disclaimer.
10a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright notice,
11a9643ea8Slogwang * this list of conditions and the following disclaimer in the documentation
12a9643ea8Slogwang * and/or other materials provided with the distribution.
13a9643ea8Slogwang *
14a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16a9643ea8Slogwang * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17a9643ea8Slogwang * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18a9643ea8Slogwang * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19a9643ea8Slogwang * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20a9643ea8Slogwang * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21a9643ea8Slogwang * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22a9643ea8Slogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23a9643ea8Slogwang * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24a9643ea8Slogwang *
25a9643ea8Slogwang */
26a9643ea8Slogwang
27a9643ea8Slogwang #include <stdlib.h>
28a9643ea8Slogwang #include <arpa/inet.h>
2910b909a1Sfengbojiang(姜凤波) #include <netinet/icmp6.h>
30a9643ea8Slogwang
31a9643ea8Slogwang #include <rte_config.h>
32a9643ea8Slogwang #include <rte_ether.h>
332bfe3f2eSlogwang #include <rte_bus_pci.h>
34a9643ea8Slogwang #include <rte_ethdev.h>
35a9643ea8Slogwang #include <rte_kni.h>
36a9643ea8Slogwang #include <rte_malloc.h>
37a9643ea8Slogwang #include <rte_ring.h>
38a9643ea8Slogwang #include <rte_ip.h>
39a9643ea8Slogwang #include <rte_tcp.h>
40a9643ea8Slogwang #include <rte_udp.h>
41a9643ea8Slogwang
42a9643ea8Slogwang #include "ff_dpdk_kni.h"
43a9643ea8Slogwang #include "ff_config.h"
44a9643ea8Slogwang
45a9643ea8Slogwang /* Callback for request of changing MTU */
46a9643ea8Slogwang /* Total octets in ethernet header */
47a9643ea8Slogwang #define KNI_ENET_HEADER_SIZE 14
48a9643ea8Slogwang
49a9643ea8Slogwang /* Total octets in the FCS */
50a9643ea8Slogwang #define KNI_ENET_FCS_SIZE 4
51a9643ea8Slogwang
52a9643ea8Slogwang #define set_bit(n, m) (n | magic_bits[m])
53a9643ea8Slogwang #define clear_bit(n, m) (n & (~magic_bits[m]))
54a9643ea8Slogwang #define get_bit(n, m) (n & magic_bits[m])
55a9643ea8Slogwang
56a9643ea8Slogwang static const int magic_bits[8] = {
57a9643ea8Slogwang 0x80, 0x40, 0x20, 0x10,
58a9643ea8Slogwang 0x8, 0x4, 0x2, 0x1
59a9643ea8Slogwang };
60a9643ea8Slogwang
61a9643ea8Slogwang static unsigned char *udp_port_bitmap = NULL;
62a9643ea8Slogwang static unsigned char *tcp_port_bitmap = NULL;
63a9643ea8Slogwang
64a9643ea8Slogwang /* Structure type for recording kni interface specific stats */
65a9643ea8Slogwang struct kni_interface_stats {
66a9643ea8Slogwang struct rte_kni *kni;
67a9643ea8Slogwang
68a9643ea8Slogwang /* number of pkts received from NIC, and sent to KNI */
69a9643ea8Slogwang uint64_t rx_packets;
70a9643ea8Slogwang
71a9643ea8Slogwang /* number of pkts received from NIC, but failed to send to KNI */
72a9643ea8Slogwang uint64_t rx_dropped;
73a9643ea8Slogwang
74a9643ea8Slogwang /* number of pkts received from KNI, and sent to NIC */
75a9643ea8Slogwang uint64_t tx_packets;
76a9643ea8Slogwang
77a9643ea8Slogwang /* number of pkts received from KNI, but failed to send to NIC */
78a9643ea8Slogwang uint64_t tx_dropped;
79a9643ea8Slogwang };
80a9643ea8Slogwang
81a9643ea8Slogwang struct rte_ring **kni_rp;
82a9643ea8Slogwang struct kni_interface_stats **kni_stat;
83a9643ea8Slogwang
84a9643ea8Slogwang static void
set_bitmap(uint16_t port,unsigned char * bitmap)85a9643ea8Slogwang set_bitmap(uint16_t port, unsigned char *bitmap)
86a9643ea8Slogwang {
87a9643ea8Slogwang port = htons(port);
88a9643ea8Slogwang unsigned char *p = bitmap + port/8;
89a9643ea8Slogwang *p = set_bit(*p, port % 8);
90a9643ea8Slogwang }
91a9643ea8Slogwang
92a9643ea8Slogwang static int
get_bitmap(uint16_t port,unsigned char * bitmap)93a9643ea8Slogwang get_bitmap(uint16_t port, unsigned char *bitmap)
94a9643ea8Slogwang {
95a9643ea8Slogwang unsigned char *p = bitmap + port/8;
96a9643ea8Slogwang return get_bit(*p, port % 8) > 0 ? 1 : 0;
97a9643ea8Slogwang }
98a9643ea8Slogwang
99a9643ea8Slogwang static void
kni_set_bitmap(const char * p,unsigned char * port_bitmap)100a9643ea8Slogwang kni_set_bitmap(const char *p, unsigned char *port_bitmap)
101a9643ea8Slogwang {
102a9643ea8Slogwang int i;
103a9643ea8Slogwang const char *head, *tail, *tail_num;
104a9643ea8Slogwang if(!p)
105a9643ea8Slogwang return;
106a9643ea8Slogwang
107a9643ea8Slogwang head = p;
108a9643ea8Slogwang while (1) {
109a9643ea8Slogwang tail = strstr(head, ",");
110a9643ea8Slogwang tail_num = strstr(head, "-");
111a9643ea8Slogwang if(tail_num && (!tail || tail_num < tail - 1)) {
112a9643ea8Slogwang for(i = atoi(head); i <= atoi(tail_num + 1); ++i) {
113a9643ea8Slogwang set_bitmap(i, port_bitmap);
114a9643ea8Slogwang }
115a9643ea8Slogwang } else {
116a9643ea8Slogwang set_bitmap(atoi(head), port_bitmap);
117a9643ea8Slogwang }
118a9643ea8Slogwang
119a9643ea8Slogwang if(!tail)
120a9643ea8Slogwang break;
121a9643ea8Slogwang
122a9643ea8Slogwang head = tail + 1;
123a9643ea8Slogwang }
124a9643ea8Slogwang }
125a9643ea8Slogwang
126a9643ea8Slogwang /* Currently we don't support change mtu. */
127a9643ea8Slogwang static int
kni_change_mtu(uint16_t port_id,unsigned new_mtu)1282bfe3f2eSlogwang kni_change_mtu(uint16_t port_id, unsigned new_mtu)
129a9643ea8Slogwang {
130a9643ea8Slogwang return 0;
131a9643ea8Slogwang }
132a9643ea8Slogwang
133a9643ea8Slogwang static int
kni_config_network_interface(uint16_t port_id,uint8_t if_up)1342bfe3f2eSlogwang kni_config_network_interface(uint16_t port_id, uint8_t if_up)
135a9643ea8Slogwang {
136a9643ea8Slogwang int ret = 0;
137a9643ea8Slogwang
138e8591dc5Sfengbojiang(姜凤波) if (!rte_eth_dev_is_valid_port(port_id)) {
139a9643ea8Slogwang printf("Invalid port id %d\n", port_id);
140a9643ea8Slogwang return -EINVAL;
141a9643ea8Slogwang }
142a9643ea8Slogwang
143a9643ea8Slogwang printf("Configure network interface of %d %s\n",
144a9643ea8Slogwang port_id, if_up ? "up" : "down");
145a9643ea8Slogwang
146a9643ea8Slogwang ret = (if_up) ?
147a9643ea8Slogwang rte_eth_dev_set_link_up(port_id) :
148a9643ea8Slogwang rte_eth_dev_set_link_down(port_id);
149a9643ea8Slogwang
150f47e38d9Slogwang if(-ENOTSUP == ret) {
151f47e38d9Slogwang if (if_up != 0) {
152f47e38d9Slogwang /* Configure network interface up */
153f47e38d9Slogwang rte_eth_dev_stop(port_id);
154f47e38d9Slogwang ret = rte_eth_dev_start(port_id);
155f47e38d9Slogwang } else {
156f47e38d9Slogwang /* Configure network interface down */
157f47e38d9Slogwang rte_eth_dev_stop(port_id);
158f47e38d9Slogwang ret = 0;
159f47e38d9Slogwang }
160f47e38d9Slogwang }
161f47e38d9Slogwang
162a9643ea8Slogwang if (ret < 0)
163a9643ea8Slogwang printf("Failed to Configure network interface of %d %s\n",
164a9643ea8Slogwang port_id, if_up ? "up" : "down");
165a9643ea8Slogwang
166a9643ea8Slogwang return ret;
167a9643ea8Slogwang }
168a9643ea8Slogwang
169e8591dc5Sfengbojiang(姜凤波) static void
print_ethaddr(const char * name,struct rte_ether_addr * mac_addr)1704418919fSjohnjiang print_ethaddr(const char *name, struct rte_ether_addr *mac_addr)
171e8591dc5Sfengbojiang(姜凤波) {
1724418919fSjohnjiang char buf[RTE_ETHER_ADDR_FMT_SIZE];
1734418919fSjohnjiang rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, mac_addr);
174e8591dc5Sfengbojiang(姜凤波) printf("\t%s%s\n", name, buf);
175e8591dc5Sfengbojiang(姜凤波) }
176e8591dc5Sfengbojiang(姜凤波)
177e8591dc5Sfengbojiang(姜凤波)
178e8591dc5Sfengbojiang(姜凤波) /* Callback for request of configuring mac address */
179e8591dc5Sfengbojiang(姜凤波) static int
kni_config_mac_address(uint16_t port_id,uint8_t mac_addr[])180e8591dc5Sfengbojiang(姜凤波) kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[])
181e8591dc5Sfengbojiang(姜凤波) {
182e8591dc5Sfengbojiang(姜凤波) int ret = 0;
183e8591dc5Sfengbojiang(姜凤波)
184e8591dc5Sfengbojiang(姜凤波) if (!rte_eth_dev_is_valid_port(port_id)) {
185e8591dc5Sfengbojiang(姜凤波) printf("Invalid port id %d\n", port_id);
186e8591dc5Sfengbojiang(姜凤波) return -EINVAL;
187e8591dc5Sfengbojiang(姜凤波) }
188e8591dc5Sfengbojiang(姜凤波)
1894418919fSjohnjiang print_ethaddr("Address:", (struct rte_ether_addr *)mac_addr);
190e8591dc5Sfengbojiang(姜凤波)
191e8591dc5Sfengbojiang(姜凤波) ret = rte_eth_dev_default_mac_addr_set(port_id,
1924418919fSjohnjiang (struct rte_ether_addr *)mac_addr);
193e8591dc5Sfengbojiang(姜凤波) if (ret < 0)
194e8591dc5Sfengbojiang(姜凤波) printf("Failed to config mac_addr for port %d\n", port_id);
195e8591dc5Sfengbojiang(姜凤波)
196e8591dc5Sfengbojiang(姜凤波) return ret;
197e8591dc5Sfengbojiang(姜凤波) }
198e8591dc5Sfengbojiang(姜凤波)
199a9643ea8Slogwang static int
kni_process_tx(uint16_t port_id,uint16_t queue_id,struct rte_mbuf ** pkts_burst,unsigned count)2002bfe3f2eSlogwang kni_process_tx(uint16_t port_id, uint16_t queue_id,
201a9643ea8Slogwang struct rte_mbuf **pkts_burst, unsigned count)
202a9643ea8Slogwang {
203a9643ea8Slogwang /* read packet from kni ring(phy port) and transmit to kni */
204a9643ea8Slogwang uint16_t nb_tx, nb_kni_tx;
2052bfe3f2eSlogwang nb_tx = rte_ring_dequeue_burst(kni_rp[port_id], (void **)pkts_burst, count, NULL);
206a9643ea8Slogwang
207a9643ea8Slogwang /* NB.
208a9643ea8Slogwang * if nb_tx is 0,it must call rte_kni_tx_burst
209a9643ea8Slogwang * must Call regularly rte_kni_tx_burst(kni, NULL, 0).
210a9643ea8Slogwang * detail https://embedded.communities.intel.com/thread/6668
211a9643ea8Slogwang */
212a9643ea8Slogwang nb_kni_tx = rte_kni_tx_burst(kni_stat[port_id]->kni, pkts_burst, nb_tx);
213a9643ea8Slogwang rte_kni_handle_request(kni_stat[port_id]->kni);
214a9643ea8Slogwang if(nb_kni_tx < nb_tx) {
215a9643ea8Slogwang uint16_t i;
216a9643ea8Slogwang for(i = nb_kni_tx; i < nb_tx; ++i)
217a9643ea8Slogwang rte_pktmbuf_free(pkts_burst[i]);
218a9643ea8Slogwang
219a9643ea8Slogwang kni_stat[port_id]->rx_dropped += (nb_tx - nb_kni_tx);
220a9643ea8Slogwang }
221a9643ea8Slogwang
222a9643ea8Slogwang kni_stat[port_id]->rx_packets += nb_kni_tx;
223a9643ea8Slogwang return 0;
224a9643ea8Slogwang }
225a9643ea8Slogwang
226a9643ea8Slogwang static int
kni_process_rx(uint16_t port_id,uint16_t queue_id,struct rte_mbuf ** pkts_burst,unsigned count)2272bfe3f2eSlogwang kni_process_rx(uint16_t port_id, uint16_t queue_id,
228a9643ea8Slogwang struct rte_mbuf **pkts_burst, unsigned count)
229a9643ea8Slogwang {
230a9643ea8Slogwang uint16_t nb_kni_rx, nb_rx;
231a9643ea8Slogwang
232a9643ea8Slogwang /* read packet from kni, and transmit to phy port */
233a9643ea8Slogwang nb_kni_rx = rte_kni_rx_burst(kni_stat[port_id]->kni, pkts_burst, count);
234a9643ea8Slogwang if (nb_kni_rx > 0) {
235a9643ea8Slogwang nb_rx = rte_eth_tx_burst(port_id, queue_id, pkts_burst, nb_kni_rx);
236a9643ea8Slogwang if (nb_rx < nb_kni_rx) {
237a9643ea8Slogwang uint16_t i;
238a9643ea8Slogwang for(i = nb_rx; i < nb_kni_rx; ++i)
239a9643ea8Slogwang rte_pktmbuf_free(pkts_burst[i]);
240a9643ea8Slogwang
241a9643ea8Slogwang kni_stat[port_id]->tx_dropped += (nb_kni_rx - nb_rx);
242a9643ea8Slogwang }
243a9643ea8Slogwang
244a9643ea8Slogwang kni_stat[port_id]->tx_packets += nb_rx;
245a9643ea8Slogwang }
246a9643ea8Slogwang return 0;
247a9643ea8Slogwang }
248a9643ea8Slogwang
249a9643ea8Slogwang static enum FilterReturn
protocol_filter_l4(uint16_t port,unsigned char * bitmap)250a9643ea8Slogwang protocol_filter_l4(uint16_t port, unsigned char *bitmap)
251a9643ea8Slogwang {
252a9643ea8Slogwang if(get_bitmap(port, bitmap)) {
253a9643ea8Slogwang return FILTER_KNI;
254a9643ea8Slogwang }
255a9643ea8Slogwang
256a9643ea8Slogwang return FILTER_UNKNOWN;
257a9643ea8Slogwang }
258a9643ea8Slogwang
259a9643ea8Slogwang static enum FilterReturn
protocol_filter_tcp(const void * data,uint16_t len)260a9643ea8Slogwang protocol_filter_tcp(const void *data, uint16_t len)
261a9643ea8Slogwang {
2624418919fSjohnjiang if (len < sizeof(struct rte_tcp_hdr))
263a9643ea8Slogwang return FILTER_UNKNOWN;
264a9643ea8Slogwang
2654418919fSjohnjiang const struct rte_tcp_hdr *hdr;
2664418919fSjohnjiang hdr = (const struct rte_tcp_hdr *)data;
267a9643ea8Slogwang
268a9643ea8Slogwang return protocol_filter_l4(hdr->dst_port, tcp_port_bitmap);
269a9643ea8Slogwang }
270a9643ea8Slogwang
271a9643ea8Slogwang static enum FilterReturn
protocol_filter_udp(const void * data,uint16_t len)272a9643ea8Slogwang protocol_filter_udp(const void* data,uint16_t len)
273a9643ea8Slogwang {
2744418919fSjohnjiang if (len < sizeof(struct rte_udp_hdr))
275a9643ea8Slogwang return FILTER_UNKNOWN;
276a9643ea8Slogwang
2774418919fSjohnjiang const struct rte_udp_hdr *hdr;
2784418919fSjohnjiang hdr = (const struct rte_udp_hdr *)data;
279a9643ea8Slogwang
280a9643ea8Slogwang return protocol_filter_l4(hdr->dst_port, udp_port_bitmap);
281a9643ea8Slogwang }
282a9643ea8Slogwang
283d7140ab7Sfengbojiang(姜凤波) #ifdef INET6
284d7140ab7Sfengbojiang(姜凤波) /*
285d7140ab7Sfengbojiang(姜凤波) * https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml
286d7140ab7Sfengbojiang(姜凤波) */
287d7140ab7Sfengbojiang(姜凤波) #ifndef IPPROTO_HIP
288d7140ab7Sfengbojiang(姜凤波) #define IPPROTO_HIP 139
289d7140ab7Sfengbojiang(姜凤波) #endif
290d7140ab7Sfengbojiang(姜凤波)
291d7140ab7Sfengbojiang(姜凤波) #ifndef IPPROTO_SHIM6
292d7140ab7Sfengbojiang(姜凤波) #define IPPROTO_SHIM6 140
293d7140ab7Sfengbojiang(姜凤波) #endif
29434e766d2S10077240
29534e766d2S10077240 #ifndef IPPROTO_MH
29634e766d2S10077240 #define IPPROTO_MH 135
29734e766d2S10077240 #endif
298d7140ab7Sfengbojiang(姜凤波) static int
get_ipv6_hdr_len(uint8_t * proto,void * data,uint16_t len)299d7140ab7Sfengbojiang(姜凤波) get_ipv6_hdr_len(uint8_t *proto, void *data, uint16_t len)
300a9643ea8Slogwang {
301d7140ab7Sfengbojiang(姜凤波) int ext_hdr_len = 0;
302d7140ab7Sfengbojiang(姜凤波)
303d7140ab7Sfengbojiang(姜凤波) switch (*proto) {
304d7140ab7Sfengbojiang(姜凤波) case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_DSTOPTS:
305d7140ab7Sfengbojiang(姜凤波) case IPPROTO_MH: case IPPROTO_HIP: case IPPROTO_SHIM6:
306d7140ab7Sfengbojiang(姜凤波) ext_hdr_len = *((uint8_t *)data + 1) + 1;
307d7140ab7Sfengbojiang(姜凤波) break;
308d7140ab7Sfengbojiang(姜凤波) case IPPROTO_FRAGMENT:
309d7140ab7Sfengbojiang(姜凤波) ext_hdr_len = 8;
310d7140ab7Sfengbojiang(姜凤波) break;
311d7140ab7Sfengbojiang(姜凤波) case IPPROTO_AH:
312d7140ab7Sfengbojiang(姜凤波) ext_hdr_len = (*((uint8_t *)data + 1) + 2) * 4;
313d7140ab7Sfengbojiang(姜凤波) break;
314d7140ab7Sfengbojiang(姜凤波) case IPPROTO_NONE:
315d7140ab7Sfengbojiang(姜凤波) #ifdef FF_IPSEC
316d7140ab7Sfengbojiang(姜凤波) case IPPROTO_ESP:
317d7140ab7Sfengbojiang(姜凤波) //proto = *((uint8_t *)data + len - 1 - 4);
318d7140ab7Sfengbojiang(姜凤波) //ext_hdr_len = len;
319d7140ab7Sfengbojiang(姜凤波) #endif
320d7140ab7Sfengbojiang(姜凤波) default:
321d7140ab7Sfengbojiang(姜凤波) return ext_hdr_len;
322d7140ab7Sfengbojiang(姜凤波) }
323d7140ab7Sfengbojiang(姜凤波)
324d7140ab7Sfengbojiang(姜凤波) if (ext_hdr_len >= len) {
325d7140ab7Sfengbojiang(姜凤波) return len;
326d7140ab7Sfengbojiang(姜凤波) }
327d7140ab7Sfengbojiang(姜凤波)
328d7140ab7Sfengbojiang(姜凤波) *proto = *((uint8_t *)data);
329d7140ab7Sfengbojiang(姜凤波) ext_hdr_len += get_ipv6_hdr_len(proto, data + ext_hdr_len, len - ext_hdr_len);
330d7140ab7Sfengbojiang(姜凤波)
331d7140ab7Sfengbojiang(姜凤波) return ext_hdr_len;
332d7140ab7Sfengbojiang(姜凤波) }
33310b909a1Sfengbojiang(姜凤波)
33410b909a1Sfengbojiang(姜凤波) static enum FilterReturn
protocol_filter_icmp6(void * data,uint16_t len)33510b909a1Sfengbojiang(姜凤波) protocol_filter_icmp6(void *data, uint16_t len)
33610b909a1Sfengbojiang(姜凤波) {
33710b909a1Sfengbojiang(姜凤波) if (len < sizeof(struct icmp6_hdr))
33810b909a1Sfengbojiang(姜凤波) return FILTER_UNKNOWN;
33910b909a1Sfengbojiang(姜凤波)
34010b909a1Sfengbojiang(姜凤波) const struct icmp6_hdr *hdr;
34110b909a1Sfengbojiang(姜凤波) hdr = (const struct icmp6_hdr *)data;
34210b909a1Sfengbojiang(姜凤波)
34310b909a1Sfengbojiang(姜凤波) if (hdr->icmp6_type >= ND_ROUTER_SOLICIT && hdr->icmp6_type <= ND_REDIRECT)
34410b909a1Sfengbojiang(姜凤波) return FILTER_NDP;
34510b909a1Sfengbojiang(姜凤波)
34610b909a1Sfengbojiang(姜凤波) return FILTER_UNKNOWN;
34710b909a1Sfengbojiang(姜凤波) }
348d7140ab7Sfengbojiang(姜凤波) #endif
349d7140ab7Sfengbojiang(姜凤波)
350d7140ab7Sfengbojiang(姜凤波) static enum FilterReturn
protocol_filter_ip(const void * data,uint16_t len,uint16_t eth_frame_type)351d7140ab7Sfengbojiang(姜凤波) protocol_filter_ip(const void *data, uint16_t len, uint16_t eth_frame_type)
352d7140ab7Sfengbojiang(姜凤波) {
353d7140ab7Sfengbojiang(姜凤波) uint8_t proto;
354d7140ab7Sfengbojiang(姜凤波) int hdr_len;
355d7140ab7Sfengbojiang(姜凤波) void *next;
356d7140ab7Sfengbojiang(姜凤波) uint16_t next_len;
357d7140ab7Sfengbojiang(姜凤波)
3584418919fSjohnjiang if (eth_frame_type == RTE_ETHER_TYPE_IPV4) {
3594418919fSjohnjiang if(len < sizeof(struct rte_ipv4_hdr))
360a9643ea8Slogwang return FILTER_UNKNOWN;
361a9643ea8Slogwang
3624418919fSjohnjiang const struct rte_ipv4_hdr *hdr = (struct rte_ipv4_hdr *)data;
363d7140ab7Sfengbojiang(姜凤波) hdr_len = (hdr->version_ihl & 0x0f) << 2;
36449e48176Slogwang if (len < hdr_len)
36549e48176Slogwang return FILTER_UNKNOWN;
36649e48176Slogwang
367d7140ab7Sfengbojiang(姜凤波) proto = hdr->next_proto_id;
368d7140ab7Sfengbojiang(姜凤波) #ifdef INET6
3694418919fSjohnjiang } else if(eth_frame_type == RTE_ETHER_TYPE_IPV6) {
3704418919fSjohnjiang if(len < sizeof(struct rte_ipv6_hdr))
371d7140ab7Sfengbojiang(姜凤波) return FILTER_UNKNOWN;
372a9643ea8Slogwang
3734418919fSjohnjiang hdr_len = sizeof(struct rte_ipv6_hdr);
3744418919fSjohnjiang proto = ((struct rte_ipv6_hdr *)data)->proto;
375d7140ab7Sfengbojiang(姜凤波) hdr_len += get_ipv6_hdr_len(&proto, (void *)data + hdr_len, len - hdr_len);
376d7140ab7Sfengbojiang(姜凤波)
377d7140ab7Sfengbojiang(姜凤波) if (len < hdr_len)
378d7140ab7Sfengbojiang(姜凤波) return FILTER_UNKNOWN;
379d7140ab7Sfengbojiang(姜凤波) #endif
380d7140ab7Sfengbojiang(姜凤波) } else {
381d7140ab7Sfengbojiang(姜凤波) return FILTER_UNKNOWN;
382d7140ab7Sfengbojiang(姜凤波) }
383d7140ab7Sfengbojiang(姜凤波)
384d7140ab7Sfengbojiang(姜凤波) next = (void *)data + hdr_len;
385d7140ab7Sfengbojiang(姜凤波) next_len = len - hdr_len;
386d7140ab7Sfengbojiang(姜凤波)
387d7140ab7Sfengbojiang(姜凤波) switch (proto) {
388a9643ea8Slogwang case IPPROTO_TCP:
38910b909a1Sfengbojiang(姜凤波) #ifdef FF_KNI
39010b909a1Sfengbojiang(姜凤波) if (!enable_kni)
39110b909a1Sfengbojiang(姜凤波) break;
39210b909a1Sfengbojiang(姜凤波) #else
39310b909a1Sfengbojiang(姜凤波) break;
39410b909a1Sfengbojiang(姜凤波) #endif
395a9643ea8Slogwang return protocol_filter_tcp(next, next_len);
396a9643ea8Slogwang case IPPROTO_UDP:
39710b909a1Sfengbojiang(姜凤波) #ifdef FF_KNI
39810b909a1Sfengbojiang(姜凤波) if (!enable_kni)
39910b909a1Sfengbojiang(姜凤波) break;
40010b909a1Sfengbojiang(姜凤波) #else
40110b909a1Sfengbojiang(姜凤波) break;
40210b909a1Sfengbojiang(姜凤波) #endif
403a9643ea8Slogwang return protocol_filter_udp(next, next_len);
404a9643ea8Slogwang case IPPROTO_IPIP:
4054418919fSjohnjiang return protocol_filter_ip(next, next_len, RTE_ETHER_TYPE_IPV4);
406d7140ab7Sfengbojiang(姜凤波) #ifdef INET6
407d7140ab7Sfengbojiang(姜凤波) case IPPROTO_IPV6:
4084418919fSjohnjiang return protocol_filter_ip(next, next_len, RTE_ETHER_TYPE_IPV6);
40910b909a1Sfengbojiang(姜凤波) case IPPROTO_ICMPV6:
41010b909a1Sfengbojiang(姜凤波) return protocol_filter_icmp6(next, next_len);
411d7140ab7Sfengbojiang(姜凤波) #endif
412a9643ea8Slogwang }
413a9643ea8Slogwang
414a9643ea8Slogwang return FILTER_UNKNOWN;
415a9643ea8Slogwang }
416a9643ea8Slogwang
417a9643ea8Slogwang enum FilterReturn
ff_kni_proto_filter(const void * data,uint16_t len,uint16_t eth_frame_type)418d7140ab7Sfengbojiang(姜凤波) ff_kni_proto_filter(const void *data, uint16_t len, uint16_t eth_frame_type)
419a9643ea8Slogwang {
420d7140ab7Sfengbojiang(姜凤波) return protocol_filter_ip(data, len, eth_frame_type);
421a9643ea8Slogwang }
422a9643ea8Slogwang
423a9643ea8Slogwang void
ff_kni_init(uint16_t nb_ports,const char * tcp_ports,const char * udp_ports)424f47e38d9Slogwang ff_kni_init(uint16_t nb_ports, const char *tcp_ports, const char *udp_ports)
425a9643ea8Slogwang {
426a9643ea8Slogwang if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
427a9643ea8Slogwang kni_stat = rte_zmalloc("kni:stat",
428a9643ea8Slogwang sizeof(struct kni_interface_stats *) * nb_ports,
429a9643ea8Slogwang RTE_CACHE_LINE_SIZE);
430a9643ea8Slogwang if (kni_stat == NULL)
431a9643ea8Slogwang rte_exit(EXIT_FAILURE, "rte_zmalloc(1 (struct netio_kni_stat *)) "
432a9643ea8Slogwang "failed\n");
433a9643ea8Slogwang
434a9643ea8Slogwang rte_kni_init(nb_ports);
435a9643ea8Slogwang }
436a9643ea8Slogwang
437a9643ea8Slogwang uint16_t lcoreid = rte_lcore_id();
438a9643ea8Slogwang char name_buf[RTE_RING_NAMESIZE];
439a9643ea8Slogwang snprintf(name_buf, RTE_RING_NAMESIZE, "kni::ring_%d", lcoreid);
440a9643ea8Slogwang kni_rp = rte_zmalloc(name_buf,
441a9643ea8Slogwang sizeof(struct rte_ring *) * nb_ports,
442a9643ea8Slogwang RTE_CACHE_LINE_SIZE);
443a9643ea8Slogwang if (kni_rp == NULL) {
444a9643ea8Slogwang rte_exit(EXIT_FAILURE, "rte_zmalloc(%s (struct rte_ring*)) "
445a9643ea8Slogwang "failed\n", name_buf);
446a9643ea8Slogwang }
447a9643ea8Slogwang
448a9643ea8Slogwang snprintf(name_buf, RTE_RING_NAMESIZE, "kni:tcp_port_bitmap_%d", lcoreid);
449a9643ea8Slogwang tcp_port_bitmap = rte_zmalloc("kni:tcp_port_bitmap", 8192,
450a9643ea8Slogwang RTE_CACHE_LINE_SIZE);
451a9643ea8Slogwang if (tcp_port_bitmap == NULL) {
452a9643ea8Slogwang rte_exit(EXIT_FAILURE, "rte_zmalloc(%s (tcp_port_bitmap)) "
453a9643ea8Slogwang "failed\n", name_buf);
454a9643ea8Slogwang }
455a9643ea8Slogwang
456a9643ea8Slogwang snprintf(name_buf, RTE_RING_NAMESIZE, "kni:udp_port_bitmap_%d", lcoreid);
457a9643ea8Slogwang udp_port_bitmap = rte_zmalloc("kni:udp_port_bitmap", 8192,
458a9643ea8Slogwang RTE_CACHE_LINE_SIZE);
459a9643ea8Slogwang if (udp_port_bitmap == NULL) {
460a9643ea8Slogwang rte_exit(EXIT_FAILURE, "rte_zmalloc(%s (udp_port_bitmap)) "
461a9643ea8Slogwang "failed\n",name_buf);
462a9643ea8Slogwang }
463a9643ea8Slogwang
464a9643ea8Slogwang memset(tcp_port_bitmap, 0, 8192);
465a9643ea8Slogwang memset(udp_port_bitmap, 0, 8192);
466a9643ea8Slogwang
467a9643ea8Slogwang kni_set_bitmap(tcp_ports, tcp_port_bitmap);
468a9643ea8Slogwang kni_set_bitmap(udp_ports, udp_port_bitmap);
469a9643ea8Slogwang }
470a9643ea8Slogwang
471a9643ea8Slogwang void
ff_kni_alloc(uint16_t port_id,unsigned socket_id,struct rte_mempool * mbuf_pool,unsigned ring_queue_size)4722bfe3f2eSlogwang ff_kni_alloc(uint16_t port_id, unsigned socket_id,
473bed8feabSroot struct rte_mempool *mbuf_pool, unsigned ring_queue_size)
474a9643ea8Slogwang {
475a9643ea8Slogwang if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
476a9643ea8Slogwang struct rte_kni_conf conf;
477a9643ea8Slogwang struct rte_kni_ops ops;
478a9643ea8Slogwang struct rte_eth_dev_info dev_info;
47928440c50Sjfb8856606 const struct rte_pci_device *pci_dev;
48028440c50Sjfb8856606 const struct rte_bus *bus = NULL;
481a9643ea8Slogwang
482a9643ea8Slogwang kni_stat[port_id] = (struct kni_interface_stats*)rte_zmalloc(
483a9643ea8Slogwang "kni:stat_lcore",
484a9643ea8Slogwang sizeof(struct kni_interface_stats),
485a9643ea8Slogwang RTE_CACHE_LINE_SIZE);
486a9643ea8Slogwang
487a9643ea8Slogwang if (kni_stat[port_id] == NULL)
488a9643ea8Slogwang rte_panic("rte_zmalloc kni_interface_stats failed\n");
489a9643ea8Slogwang
490a9643ea8Slogwang /* only support one kni */
491a9643ea8Slogwang memset(&conf, 0, sizeof(conf));
492a9643ea8Slogwang snprintf(conf.name, RTE_KNI_NAMESIZE, "veth%u", port_id);
493a9643ea8Slogwang conf.core_id = rte_lcore_id();
494a9643ea8Slogwang conf.force_bind = 1;
495a9643ea8Slogwang conf.group_id = port_id;
496a9643ea8Slogwang uint16_t mtu;
497a9643ea8Slogwang rte_eth_dev_get_mtu(port_id, &mtu);
498a9643ea8Slogwang conf.mbuf_size = mtu + KNI_ENET_HEADER_SIZE + KNI_ENET_FCS_SIZE;
499a9643ea8Slogwang
500a9643ea8Slogwang memset(&dev_info, 0, sizeof(dev_info));
501a9643ea8Slogwang rte_eth_dev_info_get(port_id, &dev_info);
5025f73f9b9Slogwang
50328440c50Sjfb8856606 if (dev_info.device)
50428440c50Sjfb8856606 bus = rte_bus_find_by_device(dev_info.device);
50528440c50Sjfb8856606 if (bus && !strcmp(bus->name, "pci")) {
50628440c50Sjfb8856606 pci_dev = RTE_DEV_TO_PCI(dev_info.device);
50728440c50Sjfb8856606 conf.addr = pci_dev->addr;
50828440c50Sjfb8856606 conf.id = pci_dev->id;
50928440c50Sjfb8856606 }
510a9643ea8Slogwang
511e8591dc5Sfengbojiang(姜凤波) /* Get the interface default mac address */
512e8591dc5Sfengbojiang(姜凤波) rte_eth_macaddr_get(port_id,
5134418919fSjohnjiang (struct rte_ether_addr *)&conf.mac_addr);
514a9643ea8Slogwang
515a9643ea8Slogwang memset(&ops, 0, sizeof(ops));
516a9643ea8Slogwang ops.port_id = port_id;
517a9643ea8Slogwang ops.change_mtu = kni_change_mtu;
518a9643ea8Slogwang ops.config_network_if = kni_config_network_interface;
519e8591dc5Sfengbojiang(姜凤波) ops.config_mac_address = kni_config_mac_address;
520a9643ea8Slogwang
521a9643ea8Slogwang kni_stat[port_id]->kni = rte_kni_alloc(mbuf_pool, &conf, &ops);
522a9643ea8Slogwang if (kni_stat[port_id]->kni == NULL)
523a9643ea8Slogwang rte_panic("create kni on port %u failed!\n", port_id);
524a9643ea8Slogwang else
525a9643ea8Slogwang printf("create kni on port %u success!\n", port_id);
526a9643ea8Slogwang
527a9643ea8Slogwang kni_stat[port_id]->rx_packets = 0;
528a9643ea8Slogwang kni_stat[port_id]->rx_dropped = 0;
529a9643ea8Slogwang kni_stat[port_id]->tx_packets = 0;
530a9643ea8Slogwang kni_stat[port_id]->tx_dropped = 0;
531a9643ea8Slogwang }
532a9643ea8Slogwang
533a9643ea8Slogwang char ring_name[RTE_KNI_NAMESIZE];
534a9643ea8Slogwang snprintf((char*)ring_name, RTE_KNI_NAMESIZE, "kni_ring_%u", port_id);
535a9643ea8Slogwang
536a9643ea8Slogwang if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
537bed8feabSroot kni_rp[port_id] = rte_ring_create(ring_name, ring_queue_size,
538a9643ea8Slogwang socket_id, RING_F_SC_DEQ);
5397abd0fb2Slogwang
5407abd0fb2Slogwang if (rte_ring_lookup(ring_name) != kni_rp[port_id])
5417abd0fb2Slogwang rte_panic("lookup kni ring failed!\n");
542a9643ea8Slogwang } else {
543a9643ea8Slogwang kni_rp[port_id] = rte_ring_lookup(ring_name);
544a9643ea8Slogwang }
545a9643ea8Slogwang
546a9643ea8Slogwang if (kni_rp[port_id] == NULL)
547a9643ea8Slogwang rte_panic("create kni ring failed!\n");
548a9643ea8Slogwang
549a9643ea8Slogwang printf("create kni ring success, %u ring entries are now free!\n",
550a9643ea8Slogwang rte_ring_free_count(kni_rp[port_id]));
551a9643ea8Slogwang }
552a9643ea8Slogwang
553a9643ea8Slogwang void
ff_kni_process(uint16_t port_id,uint16_t queue_id,struct rte_mbuf ** pkts_burst,unsigned count)5542bfe3f2eSlogwang ff_kni_process(uint16_t port_id, uint16_t queue_id,
555a9643ea8Slogwang struct rte_mbuf **pkts_burst, unsigned count)
556a9643ea8Slogwang {
557a9643ea8Slogwang kni_process_tx(port_id, queue_id, pkts_burst, count);
558a9643ea8Slogwang kni_process_rx(port_id, queue_id, pkts_burst, count);
559a9643ea8Slogwang }
560a9643ea8Slogwang
561a9643ea8Slogwang /* enqueue the packet, and own it */
562a9643ea8Slogwang int
ff_kni_enqueue(uint16_t port_id,struct rte_mbuf * pkt)5632bfe3f2eSlogwang ff_kni_enqueue(uint16_t port_id, struct rte_mbuf *pkt)
564a9643ea8Slogwang {
565a9643ea8Slogwang int ret = rte_ring_enqueue(kni_rp[port_id], pkt);
566a9643ea8Slogwang if (ret < 0)
567a9643ea8Slogwang rte_pktmbuf_free(pkt);
568a9643ea8Slogwang
569a9643ea8Slogwang return 0;
570a9643ea8Slogwang }
571a9643ea8Slogwang
572