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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
#include <mrapp.h>
#include <marsio.h>
#include <sendpath.h>
#include <rte_ip.h>
#include <rte_ether.h>
#include <rte_version.h>
#include <assert.h>
#include <arpa/inet.h>
static inline int is_same_subnet(struct in_addr a_addr, struct in_addr b_addr, struct in_addr mask)
{
in_addr_t in_addr_a = a_addr.s_addr;
in_addr_t in_addr_b = b_addr.s_addr;
in_addr_t in_addr_mask = mask.s_addr;
return (in_addr_a & in_addr_mask) == (in_addr_b & in_addr_mask);
}
/* ======================================================================================= */
static int sendpath_vdev_l2_construct(struct mr_sendpath * sendpath,
struct rte_mbuf * mbuf[], unsigned int nr_mbuf)
{
struct __mr_sendpath_vdev * _sendpath = container_of(sendpath,
struct __mr_sendpath_vdev, _father);
for (int i = 0; i < nr_mbuf; i++)
{
struct rte_ether_hdr * ether_hdr = (struct rte_ether_hdr *)rte_pktmbuf_prepend(mbuf[i],
sizeof(struct rte_ether_hdr));
MR_VERIFY_2(ether_hdr != NULL, "Not enough space for ethernet header in mbufs. ");
#if RTE_VERSION_NUM(21, 11, 0, 0) <= RTE_VERSION
ether_hdr->src_addr = _sendpath->src_eth_addr;
ether_hdr->dst_addr = _sendpath->dst_eth_addr;
#else
ether_hdr->s_addr = _sendpath->src_eth_addr;
ether_hdr->d_addr = _sendpath->dst_eth_addr;
#endif
ether_hdr->ether_type = htons(RTE_ETHER_TYPE_IPV4);
}
return 0;
}
static int sendpath_vdev_option_get(struct mr_instance * instance, struct mr_sendpath * sendpath,
int opt, va_list va_list)
{
return 0;
}
static int sendpath_vdev_option_set(struct mr_instance * instance, struct mr_sendpath * sendpath,
int opt, va_list va_list)
{
if (opt == MR_SENDPATH_OPT_BUILD_L2)
{
unsigned int enable = va_arg(va_list, unsigned int);
sendpath->fn_l2_construct = enable ? sendpath_vdev_l2_construct : NULL;
}
else if (opt == MR_SENDPATH_OPT_HOOK_PREBUILD)
{
sendpath->fn_prebuild_hook = va_arg(va_list, void *);
sendpath->prebuild_hook_args = va_arg(va_list, void *);
}
else if (opt == MR_SENDPATH_OPT_HOOK_POSTBUILD)
{
sendpath->fn_postbuild_hook = va_arg(va_list, void *);
sendpath->postbuild_hook_args = va_arg(va_list, void *);
}
else
{
MR_ERROR("Invalided opt type in %s()", __FUNCTION__);
return -EINVAL;
}
return 0;
}
static void sendpath_vdev_destory(struct mr_sendpath * sendpath)
{
struct __mr_sendpath_vdev * _sendpath = container_of(sendpath, struct __mr_sendpath_vdev, _father);
free(_sendpath);
}
static struct mr_sendpath * sendpath_vdev_create(struct mr_instance * instance, int type, va_list va_list)
{
/* 第一个传入参数:目标虚设备句柄 */
struct mr_vdev * dest_vdev = va_arg(va_list, struct mr_vdev *);
struct __mr_sendpath_vdev * _sendpath = malloc(sizeof(struct __mr_sendpath_vdev));
memset(_sendpath, 0, sizeof(struct __mr_sendpath_vdev));
/* Parameters */
_sendpath->_father.target_vdi = dest_vdev->vdi;
_sendpath->_father.vdev = dest_vdev;
_sendpath->_father.can_use = 1;
_sendpath->_father.instance = instance;
/* Callback Functions */
_sendpath->_father.fn_destory = sendpath_vdev_destory;
_sendpath->_father.fn_option_set = sendpath_vdev_option_set;
_sendpath->_father.fn_option_get = sendpath_vdev_option_get;
return &_sendpath->_father;
}
static struct mr_sendpath * sendpath_route_create(struct mr_instance * instance, int type, va_list va_list)
{
return NULL;
}
/* ======================================================================================== */
/*
\brief 创建SendPath的统一入口函数。
采用可变参数函数。根据创建类型的不同,传输参数的类型和数量也不同。
(_1_) type = MR_SENDPATH_DEV
struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type = MR_SENDPATH_VDEV,
struct mr_vdev * vdev);
(_2_) type = MR_SENDPATH_ROUTE_NORMAL
struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type = MR_SENDPATH_ROUTE_NORMAL,
struct in_addr in_addr);
(_3_) type = MR_SENDPATH_ROUTE_SPEC_DEV
struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type = MR_SENDPATH_ROUTE_SPEC_DEV,
struct mr_vdev * vdev, struct in_addr in_addr);
\return Sendpath object handler
*/
struct mr_sendpath * marsio_sendpath_create(struct mr_instance * instance, int type, ...)
{
va_list ptr_arg;
struct mr_sendpath * sendpath = 0;
va_start(ptr_arg, type);
switch (type)
{
case MR_SENDPATH_VDEV:
sendpath = sendpath_vdev_create(instance, type, ptr_arg);
break;
case MR_SENDPATH_ROUTE_NORMAL:
case MR_SENDPATH_ROUTE_SPEC_DEV:
sendpath = sendpath_route_create(instance, type, ptr_arg);
break;
default:
MR_ERROR("Invalided sendpath type in creating sendpath, Failed. ");
sendpath = NULL;
}
va_end(ptr_arg);
return sendpath;
}
int marsio_sendpath_option_set(struct mr_instance * instance, struct mr_sendpath * sendpath, int opt, ...)
{
va_list ptr_arg;
int ret = 0;
va_start(ptr_arg, opt);
if (sendpath->fn_option_set) ret = sendpath->fn_option_set(instance, sendpath, opt, ptr_arg);
va_end(ptr_arg);
return ret;
}
int marsio_sendpath_option_get(struct mr_instance * instance, struct mr_sendpath * sendpath, int opt, ...)
{
va_list ptr_arg;
int ret = 0;
va_start(ptr_arg, opt);
if (sendpath->fn_option_get) ret = sendpath->fn_option_get(instance, sendpath, opt, ptr_arg);
va_end(ptr_arg);
return ret;
}
void marsio_sendpath_destory(struct mr_sendpath * sendpath)
{
if (sendpath->fn_destory != NULL) sendpath->fn_destory(sendpath);
assert(sendpath->fn_destory != NULL);
}
/* 以下函数用于保持兼容性 */
struct mr_sendpath * marsio_sendpath_create_by_droute(struct mr_vdev * dest_device, struct in_addr addr)
{
return marsio_sendpath_create(dest_device->instance, MR_SENDPATH_ROUTE_SPEC_DEV, dest_device, addr);
}
struct mr_sendpath * marsio_sendpath_create_by_route(struct mr_instance * instance, struct in_addr addr)
{
return marsio_sendpath_create(instance, MR_SENDPATH_ROUTE_NORMAL, addr);
}
struct mr_sendpath * marsio_sendpath_create_by_vdev(struct mr_vdev * dest_device)
{
return marsio_sendpath_create(dest_device->instance, MR_SENDPATH_VDEV, dest_device);
}
|