VPP添加接口IP地址

2024-04-01 11:12
文章标签 ip 接口 地址 vpp

本文主要是介绍VPP添加接口IP地址,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如下命令添加接口IPv4地址。

vpp# set interface ip address port6 192.168.1.11/24

配置IP地址由函数ip4_add_del_interface_address_internal处理,主要参数为接口索引,IPv4地址和掩码长度(address_length)。

clib_error_t *
ip4_add_del_interface_address (vlib_main_t * vm,u32 sw_if_index,ip4_address_t * address, u32 address_length, u32 is_del)
{               return ip4_add_del_interface_address_internal(vm, sw_if_index, address, address_length, is_del);
}

接口IPv4地址相关检查

以下函数配置接口sw_if_index的IPv4地址address,前缀长度为address_length。回环接口local0,以及未配置exact-match的VLAN子接口不支持配置IP地址。

static clib_error_t *
ip4_add_del_interface_address_internal (vlib_main_t * vm,u32 sw_if_index, ip4_address_t * address,u32 address_length, u32 is_del)
{vnet_main_t *vnm = vnet_get_main ();ip4_main_t *im = &ip4_main;ip_lookup_main_t *lm = &im->lookup_main;ip4_address_fib_t ip4_af, *addr_fib = 0;error = vnet_sw_interface_supports_addressing (vnm, sw_if_index);if (error) {vnm->api_errno = VNET_API_ERROR_UNSUPPORTED;return error;}

初始化ip4_address_fib_t结构ip4_af,

  ip4_addr_fib_init (&ip4_af, address,vec_elt (im->fib_index_by_sw_if_index, sw_if_index));vec_add1 (addr_fib, ip4_af);

检查地址是否与接口所在FIB中其它接口的地址冲突。首先,遍历接口池pool(vnm->interface_main.sw_interface),找到与配置接口sw_if_index所在FIB相同的接口。

  /* there is no support for adj-fib handling in the presence of overlapping* subnets on interfaces. Easy fix - disallow overlapping subnets, like most routers do.*/if (!is_del) {/* When adding an address check that it does not conflictwith an existing address on any interface in this table. */ip_interface_address_t *ia;vnet_sw_interface_t *sif;pool_foreach (sif, vnm->interface_main.sw_interfaces){if (im->fib_index_by_sw_if_index[sw_if_index] ==im->fib_index_by_sw_if_index[sif->sw_if_index]){

随后,遍历接口上的所有IPv4地址,检查接口上地址是否与将要配置的地址网段冲突,包括三种情况:第一,与已有地址相同网段;第二,包含已有地址;第三,已有地址包含要配置的地址网段。两次调用ip4_destination_matches_route函数实现网段冲突检查,分别用已有地址的掩码长度和配置地址的掩码长度做参数。

如果网段冲突,返回错误。但是,如果发生第一种情况,并且地址冲突的接口与参数中配置接口相同,在前缀不相等的情况下,允许配置,即允许在同一接口上配置同一网段的多个不同IPv4地址。

              foreach_ip_interface_address (&im->lookup_main, ia, sif->sw_if_index, 0 /* honor unnumbered */ ,({ip4_address_t * x = ip_interface_address_get_address(&im->lookup_main, ia);if (ip4_destination_matches_route(im, address, x, ia->address_length) ||ip4_destination_matches_route (im, x, address, address_length)){/* an intf may have >1 addr from the same prefix */if ((sw_if_index == sif->sw_if_index) && (ia->address_length == address_length) &&  (x->as_u32 != address->as_u32))continue;if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE) continue;/* error if the length or intf was different */vnm->api_errno = VNET_API_ERROR_ADDRESS_IN_USE;error = clib_error_create("failed to add %U on %U which conflicts with %U for interface %U",format_ip4_address_and_length, address, address_length, format_vnet_sw_if_index_name, vnm, sw_if_index,format_ip4_address_and_length, x, ia->address_length, format_vnet_sw_if_index_name, vnm, sif->sw_if_index);goto done;}}));}}}

在结构ip_lookup_main_t的哈希成员address_to_if_address_index中查找是否已经存在配置地址对应的地址索引if_address_index,如果此地址索引存在,由地址池中取得接口地址结构ip_interface_address_t。

  if_address_index = ip_interface_address_find (lm, addr_fib, address_length);

如果地址结构ia设置了过期标志,分两种情况处理。第一种,ia中的接口索引值与参数sw_if_index相等,认为是更新操作,去掉过期标志,处理结束。第二种,认为此地址前缀由一个接口移动到另外一个接口,删除旧接口上的地址(还是调用当前函数),在新接口上添加新地址,新地址的索引值填充到了参数if_address_index。

如果找到的地址索引if_address_index有效,并且没有过期标志,表明地址冲突,报错。如果if_address_index无效,直接调用地址添加函数ip_interface_address_add。

  if (!is_del) {                     if (~0 != if_address_index){                     ip_interface_address_t *ia = pool_elt_at_index (lm->if_address_pool, if_address_index);if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE) {if (ia->sw_if_index == sw_if_index) {/* re-adding an address during the replace action. consdier this the update. clear the flag and we're done */ia->flags &= ~IP_INTERFACE_ADDRESS_FLAG_STALE;goto done;} else {/* The prefix is moving from one interface to another. delete the stale and add the new */ip4_add_del_interface_address_internal (vm, ia->sw_if_index, address, address_length, 1);ia = NULL;error = ip_interface_address_add (lm, sw_if_index, addr_fib, address_length, &if_address_index);}} else {vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS;error = clib_error_create("Prefix %U already found on interface %U",lm->format_address_and_length, addr_fib, address_length, format_vnet_sw_if_index_name, vnm, ia->sw_if_index);}} elseerror = ip_interface_address_add (lm, sw_if_index, addr_fib, address_length, &if_address_index);}if (error) goto done;

使能接口的Feature。

  ip4_sw_interface_enable_disable (sw_if_index, !is_del);

处理接口IP地址相关路由。在接口UP状态时,调用ip4_add_interface_routes增加接口路由。函数最后调用监听接口地址变化的回调函数。

  ip4_mfib_interface_enable_disable (sw_if_index, !is_del);/* intf addr routes are added/deleted on admin up/down */if (vnet_sw_interface_is_admin_up (vnm, sw_if_index)) {if (!is_del)ip4_add_interface_routes (sw_if_index, im, ip4_af.fib_index, pool_elt_at_index(lm->if_address_pool, if_address_index));}ip4_add_del_interface_address_callback_t *cb;vec_foreach (cb, im->add_del_interface_address_callbacks)cb->function (im, cb->function_opaque, sw_if_index, address, address_length, if_address_index, is_del);

接口地址添加

对于IPv4前缀长度不能大于32,IPv6前缀长度不能大于128,前缀长度也不能为0,非法前缀长度,返回错误。

clib_error_t *
ip_interface_address_add (ip_lookup_main_t * lm, u32 sw_if_index,void *addr_fib, u32 address_length, u32 * result_if_address_index)
{vnet_main_t *vnm = vnet_get_main ();ip_interface_address_t *a, *prev;u32 pi,  /* previous index */   ai,   hi;           /* head index *//* Verify given length. */if ((address_length == 0) || (lm->is_ip6 && address_length > 128) ||(!lm->is_ip6 && address_length > 32)) {vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;return clib_error_create("%U wrong length for interface %U",lm->format_address_and_length, addr_fib, address_length, format_vnet_sw_if_index_name, vnm, sw_if_index);}

确保向量if_address_pool_index_by_sw_if_index的sw_if_index位置已经分配值,以便保存接口地址的索引。

  vec_validate_init_empty (lm->if_address_pool_index_by_sw_if_index, sw_if_index, ~0);

之后,由if_address_pool地址池中分配ip_interface_address_t结构a,初始化a。

同一接口的所有ip_interface_address_t地址结构组成一个双向链表,第一个ip_interface_address_t结构的索引保存在lm->if_address_pool_index_by_sw_if_index[sw_if_index]中。新添加的地址放在链表的末尾。

最后,返回新分配的地址池索引result_if_address_index;

  pool_get_zero (lm->if_address_pool, a);ai = a - lm->if_address_pool;hi = pi = lm->if_address_pool_index_by_sw_if_index[sw_if_index];prev = 0;while (pi != (u32) ~ 0) {prev = pool_elt_at_index (lm->if_address_pool, pi);pi = prev->next_this_sw_interface;}pi = prev ? prev - lm->if_address_pool : (u32) ~ 0;a->address_key = mhash_set (&lm->address_to_if_address_index, addr_fib, ai, /* old_value */ 0);a->address_length = address_length;a->sw_if_index = sw_if_index;a->flags = 0;a->prev_this_sw_interface = pi;a->next_this_sw_interface = ~0;if (prev) prev->next_this_sw_interface = ai;lm->if_address_pool_index_by_sw_if_index[sw_if_index] = (hi != ~0) ? hi : ai;*result_if_address_index = ai;

接口特性feature

记录接口im->ip_enabled_by_sw_if_index[sw_if_index]对应的数值,仅在首次使能的时候,开启ip4-unicast和ip4-multicast特性。仅在最后一次禁止时,关闭ip4-unicast和ip4-multicast特性。

void ip4_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
{ip4_main_t *im = &ip4_main;vnet_main_t *vnm = vnet_get_main ();vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0);/* enable/disable only on the 1<->0 transition */if (is_enable) {if (1 != ++im->ip_enabled_by_sw_if_index[sw_if_index])return;} else {ASSERT (im->ip_enabled_by_sw_if_index[sw_if_index] > 0);if (0 != --im->ip_enabled_by_sw_if_index[sw_if_index])return;}

如果使能,增加接口l3_if_count计数,否则,递减l3_if_count计数。最后,调用向量enable_disable_interface_callbacks中的注册函数,例如arp_enable_disable_interface,其操作arp-reply特性。

  vnet_feature_enable_disable ("ip4-unicast", "ip4-not-enabled", sw_if_index, !is_enable, 0, 0);vnet_feature_enable_disable ("ip4-multicast", "ip4-not-enabled", sw_if_index, !is_enable, 0, 0);if (is_enable)hi->l3_if_count++;else if (hi->l3_if_count)hi->l3_if_count--;{ip4_enable_disable_interface_callback_t *cb;vec_foreach (cb, im->enable_disable_interface_callbacks)cb->function (im, cb->function_opaque, sw_if_index, is_enable);}

参见如下接口features的变化。

vpp# show interface features port6
ip4-unicast:none configuredip4-multicast:none configuredvpp# show interface features port6
ip4-unicast:ip4-not-enabledip4-multicast:ip4-not-enabled

接口地址相关多播路由表项

增加Multicast FIB标志的特殊表项。

void ip4_mfib_interface_enable_disable (u32 sw_if_index, int is_enable)
{  const fib_route_path_t path = {.frp_proto = DPO_PROTO_IP4,.frp_addr = zero_addr,.frp_sw_if_index = sw_if_index,.frp_fib_index = ~0,.frp_weight = 1,.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,};mfib_index = ip4_mfib_table_get_index_for_sw_if_index(sw_if_index);for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++) {if (is_enable) {mfib_table_entry_path_update(mfib_index, &ip4_specials[ii],MFIB_SOURCE_SPECIAL, MFIB_ENTRY_FLAG_NONE, &path);}}

如下两个特殊表项:(,224.0.0.1)/32和(,224.0.0.2)/32。

static const mfib_prefix_t ip4_specials[] =
{/* ALL prefixes are in network order */{/* (*,224.0.0.1)/32 - all hosts */.fp_grp_addr = {.ip4.data_u32 = 0x010000e0,},.fp_len = 32,.fp_proto = FIB_PROTOCOL_IP4,},{/* (*,224.0.0.2)/32 - all routers */.fp_grp_addr = {.ip4.data_u32 = 0x020000e0,},.fp_len = 32,.fp_proto = FIB_PROTOCOL_IP4,},
};

接口地址路由

根据IPv4地址,添加接口相关路由。

static void
ip4_add_interface_routes (u32 sw_if_index, ip4_main_t * im, u32 fib_index, ip_interface_address_t * a)
{ip_lookup_main_t *lm = &im->lookup_main;ip4_address_t *address = ip_interface_address_get_address (lm, a);fib_prefix_t pfx = {.fp_len = 32,.fp_proto = FIB_PROTOCOL_IP4,.fp_addr.ip4 = *address,};/* set special routes for the prefix if needed */ip4_add_interface_prefix_routes (im, sw_if_index, fib_index, a);

函数ip4_add_interface_prefix_routes首先添加的前缀路由如下,表项标志connected,attached:

vpp# show fib entry 38
38@9.9.9.0/24 fib:0 index:38 locks:2interface refs:1 entry-flags:connected,attached, src-flags:added,contributing,active, cover:-1path-list:[74] locks:2 uPRF-list:43 len:1 itfs:[2, ]path:[80] pl-index:74 ip4 weight=1 pref=0 attached:  oper-flags:resolved, cfg-flags:glean,port7forwarding:   unicast-ip4-chain[@0]: dpo-load-balance: [proto:ip4 index:40 buckets:1 uRPF:43 to:[0:0]][0] [@4]: ipv4-glean: [src:9.9.9.0/24] port7: mtu:9000 next:1 flags:[] ffffffffffff0060e0689ff00806Delegates:covered:[{entry:41}]Children:

之后是添加一个针对接口地址前缀的路由(9.9.9.0/32),掩码为32位。

vpp# show fib entry 39
39@9.9.9.0/32 fib:0 index:39 locks:2interface refs:1 entry-flags:drop,uRPF-exempt, src-flags:added,contributing,active, cover:-1path-list:[73] locks:2 flags:drop, uPRF-list:41 len:0 itfs:[]path:[79] pl-index:73 ip4 weight=1 pref=0 special:  cfg-flags:drop,[@0]: dpo-drop ip4forwarding:   unicast-ip4-chain[@0]: dpo-load-balance: [proto:ip4 index:41 buckets:1 uRPF:44 to:[0:0]][0] [@0]: dpo-drop ip4Delegates:Children:

之后再添加网段的广播地址路由(9.9.9.255/32)。

vpp# show fib entry 40
40@9.9.9.255/32 fib:0 index:40 locks:2interface refs:1 entry-flags:drop,uRPF-exempt, src-flags:added,contributing,active, cover:-1path-list:[75] locks:2 flags:drop, uPRF-list:45 len:0 itfs:[]path:[81] pl-index:75 ip4 weight=1 pref=0 special:  cfg-flags:drop,[@0]: dpo-drop ip4forwarding:   unicast-ip4-chain[@0]: dpo-load-balance: [proto:ip4 index:42 buckets:1 uRPF:46 to:[0:0]][0] [@0]: dpo-drop ip4Delegates:Children:

如果通过命令,在接口上配置了分类表功能,以下代码增加DPO_CLASSIFY类型的DPO。

  if (sw_if_index < vec_len (lm->classify_table_index_by_sw_if_index)){u32 classify_table_index = lm->classify_table_index_by_sw_if_index[sw_if_index];if (classify_table_index != (u32) ~ 0) {dpo_id_t dpo = DPO_INVALID;dpo_set (&dpo, DPO_CLASSIFY, DPO_PROTO_IP4, classify_dpo_create (DPO_PROTO_IP4, classify_table_index));fib_table_entry_special_dpo_add (fib_index, &pfx, FIB_SOURCE_CLASSIFY, FIB_ENTRY_FLAG_NONE, &dpo);dpo_reset (&dpo);}}

最后增加接口ipv4地址对应的本地直连路由(FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL)。

  fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_INTERFACE,(FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL),DPO_PROTO_IP4, &pfx.fp_addr, sw_if_index,/* invalid FIB index */ ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
}

如下为接口地址9.9.9.1对应的本地直连(connected,local)路由。

vpp# show fib entry 41
41@9.9.9.1/32 fib:0 index:41 locks:2interface refs:1 entry-flags:connected,local, src-flags:added,contributing,active, cover:38path-list:[77] locks:2 flags:local, uPRF-list:48 len:0 itfs:[]path:[83] pl-index:77 ip4 weight=1 pref=0 receive:  oper-flags:resolved, cfg-flags:local,[@0]: dpo-receive: 9.9.9.1 on port7forwarding:   unicast-ip4-chain[@0]: dpo-load-balance: [proto:ip4 index:43 buckets:1 uRPF:48 to:[0:0]][0] [@14]: dpo-receive: 9.9.9.1 on port7Delegates:Children:

这篇关于VPP添加接口IP地址的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/867017

相关文章

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

webapp地址

F:\LSP\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

Jenkins 插件 地址证书报错问题解决思路

问题提示摘要: SunCertPathBuilderException: unable to find valid certification path to requested target...... 网上很多的解决方式是更新站点的地址,我这里修改了一个日本的地址(清华镜像也好),其实发现是解决不了上述的报错问题的,其实,最终拉去插件的时候,会提示证书的问题,几经周折找到了其中一遍博文

2024.9.8 TCP/IP协议学习笔记

1.所谓的层就是数据交换的深度,电脑点对点就是单层,物理层,加上集线器还是物理层,加上交换机就变成链路层了,有地址表,路由器就到了第三层网络层,每个端口都有一个mac地址 2.A 给 C 发数据包,怎么知道是否要通过路由器转发呢?答案:子网 3.将源 IP 与目的 IP 分别同这个子网掩码进行与运算****,相等则是在一个子网,不相等就是在不同子网 4.A 如何知道,哪个设备是路由器?答案:在 A

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a

【干货分享】基于SSM的体育场管理系统的开题报告(附源码下载地址)

中秋送好礼 中秋佳节将至,祝福大家中秋快乐,阖家幸福。本期免费分享毕业设计作品:《基于SSM的体育场管理系统》。 基于SSM的体育场管理系统的开题报告 一、课题背景与意义 随着全民健身理念的深入人心,体育场已成为广大师生和社区居民进行体育锻炼的重要场所。然而,传统的体育场管理方式存在诸多问题,如资源分配不均、预约流程繁琐、数据统计不准确等,严重影响了体育场的使用效率和用户体验。

股票数据接口-陈科肇

陈科肇 新浪财经 sz-深圳sh-上海历史分价表:http://market.finance.sina.com.cn/pricehis.php?symbol=sz000506&startdate=2016-12-27&enddate=2016-12-27历史成交明细(当日成交明细):http://vip.stock.finance.sina.com.cn/quotes_service/v