summaryrefslogtreecommitdiff
path: root/service/src/register.c
blob: 63b3d0704a66bcf587a50b32678ecac2012a9d0f (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
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*
 * 注册与预初始化阶段
 * 本阶段位于Config阶段之后,根据Config阶段读取到的
 * 配置信息,注册句柄、信息,用于后续的初始化阶段。
 * 
 * 具体包括:
 * (1)设备的预打开、注册;
 * (2)VNODE节点的注册、生产者信息注册、消费者信息注册
 * 
 * TODO:
 * 消费者信息注册不应该在此处完成。
 */

#include <rte_log.h>
#include <rte_config.h>
#include <mr_common.h>
#include <sc_common.h>
#include <mr_device.h>
#include <mr_mask.h>
#include <mr_rtdev.h>
#include <assert.h>
#include <mr_runtime.h>
#include <mr_rtdev.h>
#include <MESA_prof_load.h>
#include <mr_buffer.h>

static int sc_core_instance_register(struct sc_instance * instance)
{
	// 获取全局配置句柄和全局运行时句柄
	struct mr_global_config * g_cfg = mr_global_config_get();
	struct mr_global_ctx * g_ctx = mr_global_ctx_get();
	assert(g_cfg != NULL && g_ctx != NULL);

	// 初始化全局配置
	snprintf(g_cfg->glob_cfg_file, sizeof(g_cfg->glob_cfg_file),
		"%s", instance->local_cfgfile);

	// 初始化核心库句柄
	instance->core_instance = mr_core_instance_create(NULL);
	mr_core_default_instance_set(instance->core_instance);
	g_ctx->ctx_core = instance->core_instance;
	return 0;
}

static int sc_core_ctrlzone_register(struct sc_instance * instance)
{
	struct sc_ctrlzone * ctrlzone_iter;
	TAILQ_FOREACH(ctrlzone_iter, &instance->ctrlzone_list, next)
	{
		int ret = mr_buffer_ctrlzone_register(instance->core_instance,
			ctrlzone_iter->symbol, ctrlzone_iter->id, ctrlzone_iter->size);

		if(ret < 0)
		{
			MR_LOG(ERR, SERVICE, "Register ctrlzone %s(size=%d, id=%d) failed. ",
				ctrlzone_iter->symbol, ctrlzone_iter->size, ctrlzone_iter->id);
			return -1;
		}

		MR_LOG(INFO, SERVICE, "Register ctrlzone %s(size=%d, id=%d) successfully. \n",
			ctrlzone_iter->symbol, ctrlzone_iter->size, ctrlzone_iter->id);
	}

	return 0;
}

static int sc_core_user_pktmbuf_pool_register(struct sc_instance * instance)
{
	int ret = mr_buffer_user_pool_produce(instance->core_instance, SOCKET_ID_ANY, 
		instance->sc_param.sz_user_pktmbuf, instance->sc_param.nr_user_direct_pktmbuf, 
		instance->sc_param.sz_user_pktmbuf_cache);

	if(ret < 0)
	{
		MR_LOG(ERR, SERVICE, "Produce user pktmbuf pool(nr_pktmbuf=%d, sz_pktmbuf=%d, sz_cache=%d) failed. \n",
			instance->sc_param.sz_user_pktmbuf, instance->sc_param.nr_user_direct_pktmbuf,
			instance->sc_param.sz_user_pktmbuf_cache);
	}
	else
	{
		MR_LOG(ERR, SERVICE, "User pktmbuf pool(nr_pktmbuf=%d, sz_pktmbuf=%d, sz_cache=%d) created. \n",
			instance->sc_param.sz_user_pktmbuf, instance->sc_param.nr_user_direct_pktmbuf,
			instance->sc_param.sz_user_pktmbuf_cache);
	}

	return ret;
}

static int sc_stack_instance_register(struct sc_instance * instance)
{
	// 获取全局配置句柄和全局运行时句柄
	struct mr_global_ctx * g_ctx = mr_global_ctx_get();
	assert(g_ctx != NULL);

	// 取默认内存池地址
	instance->sk_param.def_direct_pktmbuf_pool = mr_buffer_user_direct_pool_get(
		instance->core_instance, SOCKET_ID_ANY);

	instance->sk_param.def_indirect_pktmbuf_pool = mr_buffer_user_indirect_pool_get(
		instance->core_instance, SOCKET_ID_ANY);

	// 初始化协议栈全局句柄
	instance->sk_instance = sk_instance_create(instance->core_instance, &instance->sk_param);
	g_ctx->ctx_stack = instance->sk_instance;

	// 初始化服务进程句柄
	instance->sk_serv_instance = sk_app_instance_create(instance->sk_instance, instance->procsym);
	return 0;
}

static int __mr_dev_register(struct sc_instance * instance, 
	struct sc_device * sc_dev)
{
	struct sc_param * sc_param = &instance->sc_param;

	// 没有指定队列数,采用默认的队列数
	if (sc_dev->mr_dev_param.nr_rss_rxq == 0)
		sc_dev->mr_dev_param.nr_rss_rxq = sc_param->nr_serv_thread;

	if (sc_dev->mr_dev_param.nr_rss_txq == 0)
		sc_dev->mr_dev_param.nr_rss_txq = sc_param->nr_serv_thread;

	// 打开设备
	struct mr_dev * dev = mr_device_open(instance->core_instance, 
		&sc_dev->mr_dev_param);

	// 失败
	if (unlikely(dev == NULL))
	{
		MR_LOG(WARNING, SERVICE, "Service, DeviceRegister, "
			"Cannot preopen device %s, ignore it.\n",
			sc_dev->symbol);
		return -1;
	}

	// 打开设备队列
	for (int i = 0; i < sc_param->nr_serv_thread; i++)
	{
		sc_dev->rx_devq[i] = mr_device_attach(dev, DEVQ_TYPE_RSS_RX);
		sc_dev->tx_devq[i] = mr_device_attach(dev, DEVQ_TYPE_RSS_TX);
		assert(sc_dev->rx_devq[i] != NULL && sc_dev->tx_devq[i] != NULL);
	}
	
	sc_dev->dev = dev;
	sc_dev->en_mr_dev = 1;
	return 0;
}

static int __rt_dev_register(struct sc_instance * instance,
	struct sc_device * sc_dev)
{
	struct sc_param * sc_param = &instance->sc_param;
	
	// 获取mempool指针
	struct rte_mempool * direct_pool = mr_device_direct_pool_get(sc_dev->dev);
	assert(direct_pool != NULL);
	
	// 创建运行时设备
	struct rtdev_desc * rtdev = mr_rtdev_create(instance->core_instance, sc_dev->symbol,
		direct_pool, sc_param->nr_serv_thread, sc_param->sz_tunnel,
		sc_param->sz_buffer);
	
	if (unlikely(rtdev == NULL))
	{
		MR_LOG(ERR, SERVICE, "Rtdevice %s(nr_queue=%d, sz_tunnel=%d, sz_buffer=%d) create failed. \n",
			sc_dev->symbol, sc_param->nr_serv_thread, sc_param->sz_tunnel, sc_param->sz_buffer);
		return -1;
	}

	sc_dev->rt_dev = rtdev;
	sc_dev->en_rt_dev = 1;
	
	MR_LOG(INFO, SERVICE, "Rtdevice %s(nr_queue=%d, sz_tunnel=%d, sz_buffer=%d) created. \n",
		sc_dev->symbol, sc_param->nr_serv_thread, sc_param->sz_tunnel, sc_param->sz_buffer);

	return 0;
}

static int __sk_dev_register(struct sc_instance * instance,
	struct sc_device * sc_dev)
{
	// 跳过没有启用协议栈的设备
	if(!(sc_dev->en_mr_dev && sc_dev->en_sk_dev))
	{
		MR_LOG(INFO, SERVICE, "Device %s user-mode stack is disable, ignore. \n", sc_dev->symbol);
		return 0;
	}

	// 从真实设备中,填充MAC地址等信息
	struct mr_dev * dev = mr_device_lookup(instance->core_instance, sc_dev->mr_dev_param.symbol);
	assert(dev != NULL);

	sc_dev->sk_dev_param.mtu = dev->mtu;
	ether_addr_copy(&dev->ether_addr, &sc_dev->sk_dev_param.mac_addr);
	
	struct sc_param * sc_param = &instance->sc_param;
	struct rte_mempool * direct_pool = mr_device_direct_pool_get(sc_dev->dev);
	struct rte_mempool * indirect_pool = mr_device_direct_pool_get(sc_dev->dev);
	assert(direct_pool != NULL && indirect_pool != NULL);

	sc_dev->sk_dev_param.direct_pktmbuf_pool = direct_pool;
	sc_dev->sk_dev_param.indirect_pktmbuf_pool = indirect_pool;
	
	// 创建设备
	int ret = sk_device_create(instance->sk_instance, &sc_dev->sk_dev_param);
	
	if(unlikely(ret < 0))
	{
		MR_LOG(WARNING, SERVICE, "StackDevice %s create failed. \n", sc_dev->sk_dev_param.symbol);
		return -1;
	}

	// 打开设备,主应用只启用自循环收发队列,不启用TCP/UDP队列
	struct sk_dev_open_param dev_open_param;
	snprintf(dev_open_param.symbol, sizeof(dev_open_param.symbol), "%s", sc_dev->symbol);
	dev_open_param.mode = SK_DEV_MODE_SERV;
	dev_open_param.nr_loop_rxstream = sc_param->nr_serv_thread;
	dev_open_param.nr_loop_txstream = sc_param->nr_serv_thread;
	dev_open_param.nr_tcp_rxstream = 0;
	dev_open_param.nr_tcp_txstream = 0;
	dev_open_param.nr_udp_rxstream = 0;
	dev_open_param.nr_udp_txstream = 0;
	
	struct sk_dev_desc * dev_desc = sk_device_open(instance->sk_serv_instance, &dev_open_param);
	if (unlikely(dev_desc == NULL))
	{
		MR_LOG(WARNING, SERVICE, "StackDevice %s open failed. \n", sc_dev->sk_dev_param.symbol);
		return -2;
	}
	
	sc_dev->sk_dev = dev_desc;
	sc_dev->en_sk_dev = 1;
	MR_LOG(INFO, SERVICE, "StackDevice %s created. \n", sc_dev->sk_dev_param.symbol);
	return 0;
}

static int sc_device_register(struct sc_instance * instance)
{
	// 设备队列数与进程内线程最大数相同
	// 预留功能:对于每一个设备,使用不同的线程进行收发包
	struct sc_device * device_iter;
	int ret = 0;
	
	TAILQ_FOREACH(device_iter, &instance->device_list, next)
	{
		ret = __mr_dev_register(instance, device_iter);
		if (ret < 0) goto device_open_fail;
		ret = __rt_dev_register(instance, device_iter);
		if (ret < 0) goto device_open_fail;
		ret = __sk_dev_register(instance, device_iter);
		if (ret < 0) goto device_open_fail;
		
		// 打开成功,保留在设备链表中。
		instance->nr_devs++;
		continue;

		// 打开失败,移除设备链表
device_open_fail:
		MR_LOG(ERR, SERVICE, "Device %s register failed. Disabled. \n", device_iter->symbol);
		TAILQ_REMOVE(&instance->device_list, device_iter, next);
	}
	
	return 0;
}

int sc_app_register(struct sc_instance * instance)
{
	// 注册主应用
	int ret = mr_app_manager_appinfo_register(instance->procsym, instance->cpu_mask);
	if(ret < 0)
	{
		MR_LOG(ERR, SERVICE, "Cannot register service application(sym=%s, cpu_mask=%"PRIx64")",
			instance->procsym, instance->cpu_mask);
		return ret;
	}

	MR_LOG(INFO, SERVICE, "App(symbol=%s) Process(cpu_mask=%"PRIx64") registered.\n",
		instance->procsym, instance->cpu_mask);
	
	return 0;
}

extern void sc_keepalive_failure_handler(void *data, const int id_core);

int sc_keepalive_register(struct sc_instance * instance)
{
	if (!instance->sc_param.keepalive) return 0;

	instance->keepalive = rte_keepalive_create(sc_keepalive_failure_handler, instance);
	if(instance->keepalive == NULL)
	{
		MR_LOG(ERR, SERVICE, "Cannot register spinlock check info. \n");
		return -1;
	}

	MR_LOG(INFO, SERVICE, "Spinlock check registerd.\n");
	return 0;
}

void sc_stage_register(struct sc_instance * instance)
{
	MR_CHECK(sc_core_instance_register(instance) >= 0,
		"Cannot register core instance, Failed. Please recheck runtime log. ");
	MR_CHECK(sc_core_ctrlzone_register(instance) >= 0,
		"Cannot register control zone, Failed. Please recheck runtime log.");
	MR_CHECK(sc_core_user_pktmbuf_pool_register(instance) >= 0,
		"Cannot register control zone, Failed. Please recheck runtime log.");
	MR_CHECK(sc_stack_instance_register(instance) >= 0,
		"Cannot register stack instance, Failed. Please recheck runtime log. ");
	MR_CHECK(sc_app_register(instance) >= 0,
		"Cannot register process, Failed. Please recheck runtime log. ");
	MR_CHECK(sc_device_register(instance) >= 0,
		"Cannot register device, Failed. Please recheck runtime log. ");
	MR_CHECK(sc_keepalive_register(instance) >= 0,
		"Cannot register device, Failed. Please recheck runtime log. ");

	return;
}