Skip to content

Commit 4c8dc61

Browse files
author
wanlebing
committed
introduce kni isolate rx queue support
add lock to protocol safty of netdev flow api
1 parent e15f7eb commit 4c8dc61

11 files changed

+1760
-7
lines changed

conf/dpvs.conf.items

+10
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ netif_defs {
4242
}
4343
! promisc_mode <disable>
4444
! kni_name dpdk0.kni <char[32]>
45+
! kni_isolate on <on, on/off>
46+
! kni_ipaddress {
47+
! ipv4 <lan link ipv4 address>
48+
! ipv6 <lan link ipv6 address>
49+
! }
4550
}
4651

4752
<init> device dpdk1 {
@@ -57,6 +62,11 @@ netif_defs {
5762
}
5863
! promisc_mode
5964
! kni_name dpdk1.kni
65+
! kni_isolate on <on, on/off>
66+
! kni_ipaddress {
67+
! ipv4 <wan link ipv4 address>
68+
! ipv6 <wan link ipv6 address>
69+
! }
6070
}
6171

6272
<init> device bond0 {

conf/dpvs.conf.sample

+10
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ netif_defs {
4040
}
4141
! promisc_mode
4242
kni_name dpdk0.kni
43+
kni_isolate on
44+
kni_ipaddress {
45+
ipv4 192.168.0.1
46+
ipv6 0000:0000:0000:0000:0000:FFFF:C0A8:0001
47+
}
4348
}
4449

4550
<init> device dpdk1 {
@@ -59,6 +64,11 @@ netif_defs {
5964
}
6065
! promisc_mode
6166
kni_name dpdk1.kni
67+
kni_isolate on
68+
kni_ipaddress {
69+
ipv4 192.168.0.2
70+
ipv6 0000:0000:0000:0000:0000:FFFF:C0A8:0002
71+
}
6272
}
6373

6474
! <init> bonding bond0 {

conf/dpvs.conf.single-nic.sample

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ netif_defs {
3939
}
4040
! promisc_mode
4141
kni_name dpdk0.kni
42+
kni_isolate on
43+
kni_ipaddress {
44+
ipv4 192.168.0.2
45+
ipv6 0000:0000:0000:0000:0000:FFFF:C0A8:0002
46+
}
4247
}
4348
}
4449

include/kni.h

+44
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,28 @@
2929
#include <stdbool.h>
3030
#include "netif.h"
3131

32+
/*
33+
* NOTE:
34+
* 1. local ip filter will make input set fixed on ixgbe/i40e.
35+
* 2. dip filter is not supported by ixgbe and i40e under the
36+
* premise of local ip filter.
37+
* 3. use dip + dport + dst_port_mask filters to cover port range
38+
* [0-65535] to replace dip filter on ixgbe/i40e.
39+
* 4. kni fdir filter support tcp and udp, icmp not supported.
40+
* 5. if (fdir_conf.mask.dst_port_mask & pkt.dport) equal to an
41+
* element in the port_base_array, pkt will match kni fdir
42+
* filter and redirected to kni rx queue.
43+
* 6. rss rte_flow to specfic rss queue region should with lower
44+
* priority than lip and kni fdir filter.
45+
*/
46+
typedef struct kni_fdir {
47+
bool init_success; /* kni fdir init flag */
48+
uint16_t filter_mask; /* kni filter's port mask */
49+
uint16_t port_base_num; /* kni port_base num */
50+
__be16 port_base_array[DPVS_MAX_LCORE]; /* kni port_base set */
51+
uint32_t soft_id_array[DPVS_MAX_LCORE][MAX_FDIR_PROTO];
52+
} dp_vs_kni_fdir;
53+
3254
/*
3355
* @dev - real device kni attach to.
3456
* @kniname - optional, kni device name or auto generate.
@@ -38,6 +60,11 @@ int kni_add_dev(struct netif_port *dev, const char *kniname);
3860
int kni_del_dev(struct netif_port *dev);
3961
int kni_init(void);
4062

63+
int kni_fdir_init(void);
64+
int kni_fdir_filter_add(struct netif_port *dev,
65+
const union inet_addr *kni_ip,
66+
int af);
67+
4168
static inline bool kni_dev_exist(const struct netif_port *dev)
4269
{
4370
return dev->kni.kni ? true : false;
@@ -51,4 +78,21 @@ static inline void kni_handle_request(const struct netif_port *dev)
5178
rte_kni_handle_request(dev->kni.kni);
5279
}
5380

81+
static inline bool kni_fwd_valid(const struct netif_port *dev,
82+
kni_fwd_mode_t fwd_mode)
83+
{
84+
if (fwd_mode == KNI_FWD_MODE_DEFAULT) {
85+
return true;
86+
}
87+
88+
if ((fwd_mode == KNI_FWD_MODE_ISOLATE_RX)
89+
&& (dev->kni.fwd_mode == fwd_mode)
90+
&& (dev->kni.rx_queue_id != NETIF_QUEUE_ID_INVALID))
91+
{
92+
return true;
93+
}
94+
95+
return false;
96+
}
97+
5498
#endif /* __DPVS_KNI_H__ */

include/netdev_flow.h

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* DPVS is a software load balancer (Virtual Server) based on DPDK.
3+
*
4+
* Copyright (C) 2020 ByteDance (www.bytedance.com).
5+
* All Rights Reserved.
6+
*
7+
* This program is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU General Public License
9+
* as published by the Free Software Foundation; either version 2
10+
* of the License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* Copyright (C) 2020 ByteDance (www.bytedance.com).
18+
* All Rights Reserved.
19+
*
20+
* [email protected], 12/2020.
21+
*/
22+
#ifndef __NETDEV_FLOW_H__
23+
#define __NETDEV_FLOW_H__
24+
25+
#include <assert.h>
26+
#include <rte_flow.h>
27+
28+
#include "conf/common.h"
29+
#include "netif.h"
30+
31+
#ifndef NETDEV
32+
#define NETDEV
33+
#define RTE_LOGTYPE_NETDEV RTE_LOGTYPE_USER1
34+
#endif
35+
36+
#define DEFAULT_MAX_PATTERNS 6
37+
#define DEFAULT_MAX_ACTIONS 6
38+
39+
#define NETDEV_FLOW_DEFAULT_MARK_ID 1
40+
#define NETDEV_FLOW_DEFAULT_RSS_LEVEL 0
41+
42+
/* fuzzy match level with signature mode */
43+
#define DEFAULT_FUZZY_SPEC 2
44+
#define DEFAULT_FUZZY_LAST 0xfffffff0
45+
#define DEFAULT_FUZZY_MASK 0xffffffff
46+
47+
#define NETDEV_IXGBE_DRIVER_NAME "ixgbe"
48+
#define NETDEV_I40E_DRIVER_NAME "i40e"
49+
#define NETDEV_MLNX_DRIVER_NAME "net_mlx5"
50+
51+
/* flags for netdev flow */
52+
#define NETDEV_FLOW_F_SIP_FIELD (1 << 0)
53+
#define NETDEV_FLOW_F_DIP_FIELD (1 << 1)
54+
#define NETDEV_FLOW_F_SPORT_FIELD (1 << 2)
55+
#define NETDEV_FLOW_F_DPORT_FIELD (1 << 3)
56+
#define NETDEV_FLOW_F_L3_PROTO_FIELD (1 << 4)
57+
#define NETDEV_FLOW_F_L4_PROTO_FIELD (1 << 5)
58+
59+
/*
60+
* assign static priority on various flow
61+
* the smaller the priority higher on mellanox nic.
62+
*/
63+
enum netdev_flow_priority {
64+
NETDEV_FLOW_PRIORITY_NONE = 0,
65+
NETDEV_FLOW_PRIORITY_FILTER,
66+
NETDEV_FLOW_PRIORITY_VXLAN,
67+
NETDEV_FLOW_PRIORITY_RSS,
68+
};
69+
70+
/* move to next acts index, abort on failure */
71+
#define get_next_acts_index(index) do { \
72+
assert((index) < DEFAULT_MAX_ACTIONS - 1); \
73+
(index)++; \
74+
} while(0)
75+
76+
/* move to next patts index, abort on failure */
77+
#define get_next_patts_index(index) do { \
78+
assert((index) < DEFAULT_MAX_PATTERNS - 1); \
79+
(index)++; \
80+
} while(0)
81+
82+
/* netdev rss flow init */
83+
#define NETDEV_RSS_FLOW_INIT(flow, port) do { \
84+
flow->type = NETDEV_FLOW_TYPE_RSS; \
85+
flow->port_id = port->id; \
86+
flow->flow_handle = NULL; \
87+
flow->hw_offloaded = false; \
88+
flow->flow_id = netdev_flow_hash(flow); \
89+
} while(0)
90+
91+
enum netdev_flow_type {
92+
NETDEV_FLOW_TYPE_RSS,
93+
NETDEV_FLOW_TYPE_FILTER,
94+
NETDEV_FLOW_TYPE_MAX
95+
};
96+
97+
union netdev_flow_query {
98+
struct rte_flow_query_count count;
99+
struct rte_flow_action_queue queue;
100+
struct rte_flow_action_rss rss_conf;
101+
};
102+
103+
struct netdev_flow_stats {
104+
uint64_t n_pkts;
105+
uint64_t n_bytes;
106+
};
107+
108+
struct netdev_flow {
109+
enum netdev_flow_type type;
110+
portid_t port_id;
111+
112+
/* flow meta data */
113+
union {
114+
struct {
115+
queueid_t rss_queues[NETIF_MAX_QUEUES];
116+
uint32_t rss_queue_num;
117+
} rss_info;
118+
struct {
119+
queueid_t queue_id;
120+
uint16_t sport;
121+
uint16_t dport;
122+
uint8_t l3_proto;
123+
uint8_t l4_proto;
124+
union inet_addr saddr;
125+
union inet_addr daddr;
126+
} filter_info;
127+
} data;
128+
129+
uint32_t flags;
130+
/* unique flow id */
131+
uint32_t flow_id;
132+
133+
/* pointer to rte flow in hardware */
134+
struct rte_flow *flow_handle;
135+
bool hw_offloaded;
136+
struct list_head list;
137+
struct netdev_flow_stats stats;
138+
};
139+
140+
/* l4_proto used by i40e only */
141+
int netdev_flow_add_kni_filter(struct netif_port *port,
142+
const union inet_addr *kni_ip,
143+
queueid_t kni_queue_id,
144+
uint8_t l3_proto,
145+
uint8_t l4_proto);
146+
/* called on dpvs initial */
147+
int netdev_flow_add_rss_filter(struct netif_port *port);
148+
149+
/*
150+
* NOTE: netdev flow api, operate flow on initial or terminal,
151+
* need to use lock on rte_flow_* in case of concurrent.
152+
*/
153+
int netdev_flow_init(struct netif_port *port);
154+
int netdev_flow_add(struct netif_port *port,
155+
struct netdev_flow *netdev_flow);
156+
int netdev_flow_del(struct netif_port *port,
157+
struct netdev_flow *netdev_flow);
158+
int netdev_flow_query(struct netif_port *port,
159+
struct netdev_flow *netdev_flow,
160+
union netdev_flow_query *query);
161+
int netdev_flow_flush(struct netif_port *port);
162+
163+
#endif /* __NETDEV_FLOW_H__ */

include/netif.h

+37-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ enum {
5353

5454
/* max tx/rx queue number for each nic */
5555
#define NETIF_MAX_QUEUES 16
56+
/* invalid queue id for initial val */
57+
#define NETIF_QUEUE_ID_INVALID -1
58+
/* max addr count on kni interface */
59+
#define NETIF_KNI_ADDR_MAX_NUM 32
5660
/* max nic number used in the program */
5761
#define NETIF_MAX_PORTS 4096
5862
/* maximum pkt number at a single burst */
@@ -73,6 +77,8 @@ enum {
7377

7478
#define NETIF_LCORE_ID_INVALID 0xFF
7579

80+
#define MAX_FDIR_PROTO 2
81+
7682
/************************* lcore conf ***************************/
7783
struct rx_partner;
7884

@@ -166,13 +172,28 @@ typedef enum {
166172
PORT_TYPE_INVAL,
167173
} port_type_t;
168174

175+
typedef enum {
176+
KNI_FWD_MODE_DEFAULT,
177+
KNI_FWD_MODE_ISOLATE_RX,
178+
KNI_FWD_MODE_MAX,
179+
} kni_fwd_mode_t;
180+
181+
struct kni_addr {
182+
int af;
183+
union inet_addr addr;
184+
} __rte_cache_aligned;
185+
169186
struct netif_kni {
170187
char name[IFNAMSIZ];
171188
struct rte_kni *kni;
172189
struct ether_addr addr;
173190
struct dpvs_timer kni_rtnl_timer;
191+
int ip_addr_cnt; /* total count of kni addrs */
174192
int kni_rtnl_fd;
175193
struct rte_ring *rx_ring;
194+
struct kni_addr ip[NETIF_KNI_ADDR_MAX_NUM]; /* ipv4 or ipv6 */
195+
queueid_t rx_queue_id; /* only one kni queue supported by default */
196+
kni_fwd_mode_t fwd_mode; /* kni fwd mode: default or isolated rx */
176197
} __rte_cache_aligned;
177198

178199
union netif_bond {
@@ -228,6 +249,12 @@ struct netif_hw_addr_list {
228249
int count;
229250
};
230251

252+
struct flow_info {
253+
struct list_head flow_list; /* store rte flow related on port */
254+
int flow_cnt; /* current flow count */
255+
int flow_err; /* error flow count */
256+
};
257+
231258
struct netif_port {
232259
char name[IFNAMSIZ]; /* device name */
233260
portid_t id; /* device id */
@@ -255,6 +282,9 @@ struct netif_port {
255282
struct vlan_info *vlan_info; /* VLANs info for real device */
256283
struct netif_tc tc; /* traffic control */
257284
struct netif_ops *netif_ops;
285+
int rss_queue_num;
286+
queueid_t rss_queues[NETIF_MAX_QUEUES];
287+
struct flow_info hw_flow_info; /* hardware rte flow on port */
258288
} __rte_cache_aligned;
259289

260290
/**************************** lcore API *******************************/
@@ -317,7 +347,7 @@ int netif_ctrl_term(void); /* netif ctrl plane cleanup */
317347
void netif_cfgfile_init(void);
318348
void netif_keyword_value_init(void);
319349
void install_netif_keywords(void);
320-
350+
lcoreid_t netif_get_kni_lcore_id(void);
321351

322352
static inline void *netif_priv(struct netif_port *dev)
323353
{
@@ -340,4 +370,10 @@ static inline uint16_t dpvs_rte_eth_dev_count(void)
340370

341371
extern bool dp_vs_fdir_filter_enable;
342372

373+
extern bool dp_vs_kni_isolate_rx_enable;
374+
375+
typedef int (* netif_filter_op_func)(int af, struct netif_port *dev, lcoreid_t cid,
376+
const union inet_addr *dip, __be16 dport,
377+
uint32_t filter_id[], bool add);
378+
343379
#endif /* __DPVS_NETIF_H__ */

0 commit comments

Comments
 (0)