VPP 负载均衡测试代码

1. 均衡的测试思想和流程说明。

先说一下理论, 然后后边才知道 代码逻辑。

调试了两天,这个代码终于通了。 由于时间关系, 画了一个粗略的图。另外这个代码只是流程通了,不过要帮助理解负载均衡我认为已经足够了。

下面是windows 电脑发UDP 包给VPP 进行均衡的流程图:

总的来说就VPP中有两个NODE, 一个是flowtable, 一个是load balancer.

这个插件跑起来后(后边说如何跑),在VPP 中输入以下命令:

set interface loadbalanced GigabitEthernet13/0/0  to  GigabitEthernet1b/0/0

后, 就会把GigabitEthernet13/0/0 的报文全部重定向到flowtable NODE, flowtable node处理后(选择一些报文, 我们例子中选择全部) 转发到load balancer node. 然后load balancer node把报文按均衡算法从 GigabitEthernet1b/0/0 口发出去, 其实目的port 可以多设置几个, 不过我的VPP中我只加了两个Port 就只设置了一个目的 port。

图中的示例是从windows 电脑 192.168.100.103 发一个udp包给 192.168.100.200。 windows 要先发一个ARP 包, 来获取目的IP的MAC 地址, 这个ARP 广播报文到达192.168.100.200 后, 直接重定向到了flow table NODE. 在flowtable node中我把ARP 报文改成了回复报文(RARP), 然后送到了load balancer node,  然后load balance node 把包从192.168.100.201 发出去, 到达了windows 电脑。 这样windows 电脑就知道192.168.100.200 在哪里了。

windows电脑第二步发了一个UDP 包给192.168.100.200, 这个UDP 包到达192.168.100.200 后, 直接重定向到了flow table NODE. 在flowtable node中我没有做任何处理, 然后送到了load balancer node,  然后load balance node 把这个包从192.168.100.201 发出去, 因为包的内容 还是发给192.168.100.200的, 所以又送给了192.168.100.200 , 这样就死循环了。

不过没有关系 , 我们的转发, 和均衡功能 其实已经达到测试的目的 了。

2. 如何实现这个功能, 我们直接上源码:注释写得很详细了, 加上上边的说明应该没有问题。

在VPP中创建文件夹 vpp/src/plugins/flowtable , 放入以下这些文件 :

loadbalancer.h



#define debug		printf			

#define foreach_loadbalancer_error  _(PROCESSED, "Loadbalancer packets gone thru") 



typedef enum {

#define _(sym,str) LOADBALANCER_ERROR_##sym,

	foreach_loadbalancer_error
#undef _

	LOADBALANCER_N_ERROR
	
} loadbalancer_error_t;

typedef struct {

	vlib_main_t *vlib_main;
	vnet_main_t *vnet_main;

} loadbalancer_main_t;


typedef struct {

	loadbalancer_main_t *lbm;

	u32 sw_if_index_source;
	u32 *sw_if_target;
	u32 last_target_index;

} loadbalancer_runtime_t;


loadbalancer_main_t loadbalancer_main;


extern vlib_node_registration_t loadbalancer_node;



loadbalancer.c



#include "flowtable.h"
#include "loadbalancer.h"
#include <vnet/plugin/plugin.h>


int loadbalancer_set_targets(loadbalancer_main_t *lb, u32 sw_if_index_source, 
		u32 *sw_if_index_targets) {

	u32 *sw_if_index;

	debug("debug:[%s:%s:%d] loadbalancer_node.index:%d\n", __FILE__, __func__, __LINE__, loadbalancer_node.index);
	loadbalancer_runtime_t *rt = vlib_node_get_runtime_data(lb->vlib_main, loadbalancer_node.index); // 初始化时定义了runtime_t 内部的大小, 这里存出来, 存自己想要存的东西。

	debug("debug:[%s:%s:%d] sw_if_index_source:%d\n", __FILE__, __func__, __LINE__, sw_if_index_source);
	
	rt->sw_if_index_source = sw_if_index_source; // 存源Port
	vec_foreach(sw_if_index, sw_if_index_targets) { // 存目的port list
		vec_add1(rt->sw_if_target, *sw_if_index);
	}
	return 0;
}


static clib_error_t *set_lb_target_command_fn (vlib_main_t * vm, // 解析命令行
                                     unformat_input_t * input,
                                     vlib_cli_command_t * cmd) {
	flowtable_main_t *fm = &flowtable_main;
	loadbalancer_main_t *lb = &loadbalancer_main;
	
	u32 sw_if_index_source = ~0;
	u32 sw_if_index = ~0;
	u32 *sw_if_index_targets = NULL;
	
	int source = 1;
	vec_alloc(sw_if_index_targets, 10);
	//vec_validate(sw_if_index_targets, 10);

	while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) {
		if (unformat(input, "to")) {
			source = 0;
		} else if (unformat(input, "%U", unformat_vnet_sw_interface, 
			fm->vnet_main, &sw_if_index)) {
			debug("debug:[%s:%s:%d] sw_if_index:%d\n", __FILE__, __func__, __LINE__, sw_if_index);
			if (source) {
				sw_if_index_source = sw_if_index; // 解析哪个口来的数据进转发。
			} else {
				vec_add1(sw_if_index_targets, sw_if_index); //解析PACKT 被哪些口进行均衡。
			} 
		} else break;
	} 

	if (sw_if_index == ~0) {
		return clib_error_return(0, "No Source Interface specified");
	}

	if (vec_len(sw_if_index_targets) <= 0) {
		return clib_error_return(0, "No Target Interface specified");
	}

	int rv = flowtable_enable(fm, sw_if_index_source, 1); // 把源接口重定向到flowtable NODE
//	u32 *v;
//	vec_foreach(v, sw_if_index_targets) {
//		rv = flowtable_enable(fm, *v, 1);
//	}

	
	debug("debug:[%s:%s:%d] rv:%d\n", __FILE__, __func__, __LINE__, rv);

	switch(rv) {
		case 0: break;
		case VNET_API_ERROR_INVALID_SW_IF_INDEX: return clib_error_return(0, "Invalid interface");
		case VNET_API_ERROR_UNIMPLEMENTED: return clib_error_return(0, "Device driver doesn't support redirection"); break;
		default : return clib_error_return(0, "flowtable_enable return %d", rv); break;
	}

	rv = loadbalancer_set_targets(lb, sw_if_index_source, sw_if_index_targets); // 把源port , 目的port 存到runtime_t中。
	if (rv) {
		return clib_error_return(0, "set interface loadbalancer return %d", rv);
	}
	return 0;
}


VL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值