VPP接口二层互联xconnect

以下命令将接口设置为L2二层互联模式,如果要双向流量,需要两个口都设置成此模式。一个接口上接收到的报文将发送到另外一个接口,反之亦然。

vpp# set interface state HundredGigabitEthernet65/0/0 up
vpp# set interface state HundredGigabitEthernet65/0/1 up
vpp#
vpp# set interface l2 xconnect HundredGigabitEthernet65/0/0 HundredGigabitEthernet65/0/1
vpp# set interface l2 xconnect HundredGigabitEthernet65/0/1 HundredGigabitEthernet65/0/0
vpp#
vpp# show mode
l3 GigabitEthernet4/0/0
l3 GigabitEthernet5/0/0
l2 xconnect HundredGigabitEthernet65/0/0 HundredGigabitEthernet65/0/1
l2 xconnect HundredGigabitEthernet65/0/1 HundredGigabitEthernet65/0/0

一 设置接口二层互联

函数int_l2_xc处理接口二层互联。模式为MODE_L2_XC,要互联的接口为sw_if_index和xc_sw_if_index。

static clib_error_t *
int_l2_xc (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
{/* set the interface mode */if (set_int_l2_mode  (vm, vnm, MODE_L2_XC, sw_if_index, 0, L2_BD_PORT_TYPE_NORMAL,0, xc_sw_if_index)){error = clib_error_return (0, "invalid configuration for interface", format_unformat_error, input);goto done;}

核心函数set_int_l2_mode如下,获取到接口的二层输入配置l2_input_config_t,如果接口已经为互联接口,l2_if_adjust自减1,注意之后会自增回来。

u32 set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_index, u32 bd_index, l2_bd_port_type_t port_type, u32 shg, u32 xc_sw_if_index)
{l2output_main_t *l2om = &l2output_main;l2_output_config_t *out_config;l2_input_config_t *config;hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index);config = l2input_intf_config (sw_if_index);if (l2_input_is_xconnect (config))l2_if_adjust--;vec_validate_init_empty (l2om->output_node_index_vec, sw_if_index, L2OUTPUT_NEXT_DROP);

以下设置接口为二层互联模式MODE_L2_XC,接口配置标志设置为L2_INPUT_FLAG_XCONNECT,互联的对端接口xc_sw_if_index设置到配置结构的output_sw_if_index成员。

清除二层网桥相关的配置,如二层MAC自学习,转发和泛洪。在feature_bitmap中设置互联feature:L2INPUT_FEAT_XCONNECT。

  /* Initialize the l2-input configuration for the interface */if (mode == MODE_L3) { ... }else {/* Add or update l2-output node next-arc and output_node_index_vec table for the interface */l2output_create_output_node_mapping (vm, vnet_main, sw_if_index);if (mode == MODE_L2_XC) {config->flags = L2_INPUT_FLAG_XCONNECT;config->output_sw_if_index = xc_sw_if_index;config->feature_bitmap |= L2INPUT_FEAT_DROP;/* Make sure bridging features are disabled */config->feature_bitmap &= ~(L2INPUT_FEAT_LEARN | L2INPUT_FEAT_FWD | L2INPUT_FEAT_FLOOD);config->feature_bitmap |= L2INPUT_FEAT_XCONNECT;shg = 0;      /* not used in xconnect */}/* set up split-horizon group and set output feature bit */config->shg = shg;

以下设置接口的二层输出配置l2_output_config_t,水平分割组shg设置为0,xconnect互联不需要。自增l2_if_adjust,如果l2_if_adjust为1,表明接口由三层转为二层模式。

      out_config = l2output_intf_config (sw_if_index);out_config->shg = shg;out_config->feature_bitmap |= L2OUTPUT_FEAT_OUTPUT;/** Test: remove this when non-IP features can be configured.* Enable a non-IP feature to test IP feature masking* config->feature_bitmap |= L2INPUT_FEAT_CTRL_PKT;*/l2_if_adjust++;bd_input_walk (bd_index, l2input_recache, NULL);}

更新接口所属的上层硬件接口hi的二层接口数量l2_if_count。如果硬件接口为以太网接口,在生成首个二层接口时,由于需要接收所有MAC地址的报文,这里开启混杂模式。

相反,如果所有二层接口都被去除,退出混杂模式,仅接收目的MAC地址为当前接口MAC的报文。

  hi->l2_if_count += l2_if_adjust;   /* Adjust count of L2 interfaces */if (hi->hw_class_index == ethernet_hw_interface_class.index) {if ((hi->l2_if_count == 1) && (l2_if_adjust == 1)) {/* Just added first L2 interface on this port Set promiscuous mode on the l2 interface */ethernet_set_flags (vnet_main, hi->hw_if_index, ETHERNET_INTERFACE_FLAG_ACCEPT_ALL);}else if ((hi->l2_if_count == 0) && (l2_if_adjust == -1)) {/* Just removed only L2 subinterface on this port Disable promiscuous mode on the l2 interface */ethernet_set_flags (vnet_main, hi->hw_if_index, /*ETHERNET_INTERFACE_FLAG_DEFAULT_L3 */ 0);}}

设置以太网接口的L2/L3标志。以太网类设备ethernet_hw_interface_class,没有注册set_l2_mode_function函数。

  /* Set up the L2/L3 flag in the interface parsing tables */ethernet_sw_interface_set_l2_mode (vnm, sw_if_index, (mode != MODE_L3));dev_class = vnet_get_device_class (vnet_main, hi->dev_class_index);if (dev_class->set_l2_mode_function)dev_class->set_l2_mode_function (vnet_main, hi, l2_if_adjust);

二 L2OUTPUT下一节点

设置l2-output节点的下一个处理节点为硬件接口的输出节点hw0->output_node_index。在L2处理报文完毕之后,由物理接口发出报文。

/** Create a mapping in the next node mapping table for the given sw_if_index. */
void
l2output_create_output_node_mapping (vlib_main_t * vlib_main, vnet_main_t * vnet_main, u32 sw_if_index)
{     vnet_hw_interface_t *hw0 = vnet_get_sup_hw_interface (vnet_main, sw_if_index);/* dynamically create graph node arc  */u32 next = vlib_node_add_next (vlib_main, l2output_node.index,hw0->output_node_index);l2output_main.output_node_index_vec[sw_if_index] = next;  

三 Bridge Domain成员

接口L2互联使用的bridge domain为0,遍历BD中的所有成员,每个成员调用l2input_recache处理。

u32 bd_input_walk (u32 bd_index, bd_input_walk_fn_t fn, void *data)
{    l2_flood_member_t *member;l2_bridge_domain_t *bd;sw_if_index = ~0;bd = bd_get (bd_index);vec_foreach (member, bd->members) {  if (WALK_STOP == fn (bd_index, member->sw_if_index)) {sw_if_index = member->sw_if_index;break;}}return (sw_if_index);

使用BD中的值mac_age,seq_num和feature_bitmap,更新所有接口的二层输入结构中对应的成员。对于L2互联,这些操作都没有用。

walk_rc_t l2input_recache (u32 bd_index, u32 sw_if_index)
{l2_input_config_t *input;l2_bridge_domain_t *bd;bd = bd_get (bd_index);input = l2input_intf_config (sw_if_index);input->bd_mac_age = bd->mac_age;input->bd_seq_num = bd->seq_num;input->bd_feature_bitmap = bd->feature_bitmap;return (WALK_CONTINUE);

四 接口二层配置

接口的二层输入配置位于l2input_main成员向量configs中,索引为sw_if_index。

l2_input_config_t *
l2input_intf_config (u32 sw_if_index)
{l2input_main_t *mp = &l2input_main;vec_validate (mp->configs, sw_if_index);return vec_elt_at_index (mp->configs, sw_if_index);
}

接口的二层输出配置位于l2output_main成员向量configs中,索引为sw_if_index。

l2_output_config_t *
l2output_intf_config (u32 sw_if_index)
{   l2output_main_t *mp = &l2output_main;vec_validate (mp->configs, sw_if_index);return vec_elt_at_index (mp->configs, sw_if_index);
} 

五 以太网二层配置

以太网接口将对应的子接口设置为二层模式SUBINT_CONFIG_L2,如果接口为主接口,而不是子接口,设置0,1,2,3层VLAN标志,即这些报文都可以通过主接口接收。

void ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
{subint_config_t *subint;vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);subint = ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags, &placeholder_unsup);ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));if (l2) {subint->flags |= SUBINT_CONFIG_L2;if (is_port)subint->flags |= SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG| SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;

在ethernet_main中,物理接口属于没有任何tag的子接口,使用了main_intf_t结构的成员untagged_subint。

static subint_config_t *
ethernet_sw_interface_get_config (vnet_main_t * vnm, u32 sw_if_index, u32 * flags, u32 * unsupported)
{ethernet_main_t *em = &ethernet_main;main_intf_t *main_intf;subint_config_t *subint = 0;hi = vnet_get_sup_hw_interface (vnm, sw_if_index);vec_validate (em->main_intfs, hi->hw_if_index);main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0)) {// if no flags are set then this is a main interface so treat as untaggedsubint = &main_intf->untagged_subint;*flags = SUBINT_CONFIG_MATCH_0_TAG;

在ethernet-input节点接收到报文之后,取得子接口配置untagged_subint,检查其成员flags是否设置了二层标志SUBINT_CONFIG_L2,为真表示物理口(主接口)处于二层模式。对于以上的xconnect配置,main_is_l3等于0。

eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node, vnet_hw_interface_t * hi, ...)
{ethernet_main_t *em = &ethernet_main;ethernet_interface_t *ei;ei = pool_elt_at_index (em->interfaces, hi->hw_instance);main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);subint_config_t *subint0 = &intf0->untagged_subint;int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;if (main_is_l3) { ... }else {if (hi->l3_if_count == 0) {eth_input_process_frame (vm, node, hi, from, n_pkts,/*is_l3 */ 0, ip4_cksum_ok, 0);

对于没有任何VLAN信息的报文,下一个处理节点为l2-input。

static_always_inline void
eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node, vnet_hw_interface_t * hi,u32 * buffer_indices, u32 n_packets, int main_is_l3,...)
{ethernet_main_t *em = &ethernet_main;next_l2 = em->l2_next;if (main_is_l3 == 0 && etype[0] != et_vlan && etype[0] != et_dot1ad)next[0] = next_l2;

六 报文追踪

根据trace信息可知,接口HundredGigabitEthernet65/0/0接收到报文之后,处理的节点流程为:
dpdk-input --》ethernet-input --》l2-input --》l2-output --》HundredGigabitEthernet65/0/1-output --》HundredGigabitEthernet65/0/1-tx。

vpp# trace add dpdk-input 3
vpp# show trace
------------------- Start of thread 1 vpp_wk_0 -------------------
Packet 100:18:13:467725: dpdk-inputHundredGigabitEthernet65/0/0 rx queue 4IP4: 00:0d:e9:07:e4:75 -> 00:0d:e9:07:e4:74UDP: 17.1.1.100 -> 17.1.2.174
00:18:13:467752: ethernet-inputframe: flags 0x3, hw-if-index 3, sw-if-index 3IP4: 00:0d:e9:07:e4:75 -> 00:0d:e9:07:e4:74
00:18:13:467757: l2-inputl2-input: sw_if_index 3 dst 00:0d:e9:07:e4:74 src 00:0d:e9:07:e4:75 [l2-output ]
00:18:13:467758: l2-outputl2-output: sw_if_index 4 dst 00:0d:e9:07:e4:74 src 00:0d:e9:07:e4:75 data 08 00 45 00 05 dc cb bf 00 00 ff 11
00:18:13:467758: HundredGigabitEthernet65/0/1-outputHundredGigabitEthernet65/0/1IP4: 00:0d:e9:07:e4:75 -> 00:0d:e9:07:e4:74UDP: 17.1.1.100 -> 17.1.2.174tos 0x00, ttl 255, length 1500, checksum 0xc43d dscp CS0 ecn NON_ECNfragment id 0xcbbfUDP: 6006 -> 10000length 1480, checksum 0x8fc4
00:18:13:467759: HundredGigabitEthernet65/0/1-txHundredGigabitEthernet65/0/1 tx queue 1IP4: 00:0d:e9:07:e4:75 -> 00:0d:e9:07:e4:74

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/653092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大厂AI课学习笔记】1.1.2 现阶段人工智能方法和技术领域

目录 1.2 现阶段人工智能方法和技术领域 1.2.1 从技术应用场景展开 计算机视觉 语音识别 自然语言处理 1.2.2 实现AI的技术工具 机器学习的主要类型: 深度学习的重要性: 1.2 现阶段人工智能方法和技术领域 1.2.1 从技术应用场景展开 计算机视觉…

RuoYi-Vue前后端分离后台开发框架运行详细教程

一、官网下载代码 RuoYi-Vue是一款基于SpringBootVue的前后端分离极速后台开发框架。 若依官网:http://ruoyi.vip演示地址:http://vue.ruoyi.vip代码下载:https://gitee.com/y_project/RuoYi-Vue 下载之后解压,ruoyi-ui是前端代…

opencv学习二值分析

内容来源于《opencv4应用开发入门、进阶与工程化实践》 二值分析: 常见的二值化方法: 基于全局阈值(threshold)得到的二值图像;基于自适应阈值(adaptiveThreshold)得到的二值图像&#xff1…

docker数据卷的使用

文章目录 1、数据卷产生背景2、数据卷的使用2.1、创建数据卷2.2、挂载数据卷2.3、共享数据卷2.4、删除数据卷2.5、备份和迁移数据卷 总结 1、数据卷产生背景 Docker的镜像是由一系列的只读层组合而来,当启动一个容器时,Docker加载镜像的所有只读层&…

JavaScript高级:构造函数

1 引言 构造函数是一种特殊的函数&#xff0c;主要用来初始化对象&#xff1b;常规的 {...} 语法允许创建一个对象&#xff0c;但是通过构造函数可以快速创建多个类似的对象 2 约定 1. 命名以大写字母开头&#xff1b; 2. 它们只能由 “new” 操作符来执行 <script>//…

【C++】filesystem

文章目录 1. 基本配置1.1. VS2019修改C标准1.2. filesystem的引入 2. 日常使用2.1. 认识2.2. 控制台输入路径并对路径进行基本操作 <filesystem>是C 17标准引入的标准库&#xff0c;主要用于处理文件系统的目录和文件操作&#xff0c;接下来总结该库的基本配置和日常使用…

Docker搭建Mysql5.7双主双从集群步骤

记录下在Docker搭建mysql5.7双主双从集群步骤 1.拉取镜像 docker pull mysql:5.72.创建对应数据卷 由于我们需要做数据持久化,所以先在本地创建对应四个节点的相应文件夹 #conf文件夹用于存放配置文件 mkdir -p /root/mysql/mysql-master/conf #data文件夹用于存放mysql数…

BIGVGAN: A UNIVERSAL NEURAL VOCODER WITHLARGE-SCALE TRAINING——TTS论文阅读

笔记地址&#xff1a;https://flowus.cn/share/a16a61b3-fcd0-4e0e-be5a-22ba641c6792 【FlowUs 息流】Bigvgan 论文地址&#xff1a; BigVGAN: A Universal Neural Vocoder with Large-Scale Training Abstract 背景&#xff1a; 最近基于生成对抗网络&#xff08;GAN&am…

【第十八课】DFS:深度优先搜索( acwing-843 n-皇后问题 / c++代码 )

目录 错误写法(可跳 DFS-剪枝 代码 思路二&#xff1a; 原始解法 错误写法(可跳 看到这道题&#xff0c;我想这不还是n个数的全排列的问题么?也就是把数字变成了字符&#xff0c;一些输出格式上的变化。于是就在原有代码上修改一下应该就行。 我的思路就还是path存有可能…

跨站脚本攻击漏洞概述-XSS

什么是跨站脚本攻击 跨站脚本( Cross-site Scripting ) 攻击&#xff0c;攻击者通过网站注入点注入客户端可执行解析的payload(脚本代码)&#xff0c;当用户访问网页时&#xff0c;恶意payload自动加载并执行&#xff0c;以达到攻击者目的(窃取cookie、恶意传播、钓鱼欺骗等)。…

十大排序算法之非线性时间比较类排序

前言 接下来就开始我们的算法学习之路了&#xff0c;代码会分别使用Java与Python来实现&#xff0c;数据处理的算法很多&#xff0c;排序是最基础且最重要的一类&#xff0c;大多数人都是通过学习排序算法入门的。接下来让我们一起学习闻名遐迩的十大排序算法&#xff0c;它们…

非官方 Bevy 作弊书07-09

源自 网页 Working with 2D - Unofficial Bevy Cheat Book 个人用 有道 翻译&#xff0c;希望能够帮助像我一样的 英语不好 的 bevy 初学者 非官方 Bevy 作弊书 7 使用 bevy 2D 本章涵盖与使用 Bevy 制作 2D 游戏相关的主题。 2D Camera Setup - Unofficial Bevy Cheat Book 非…

java.util.LinkedHashMap cannot be cast to xxx

java.util.LinkedHashMap cannot be cast to com.entity.Person 使用mybatis, resultMap映射的是实体类Person, 查询出来的结果是一个ArrayList,然后结果存放在一个ListObject的data属性中, 存放结果的类 public class ListObject { private Object data; public Object get…

R语言【taxlist】——match_names():字符和 taxlist 对象之间的搜索匹配

Package taxlist version 0.2.4 Description 字符向量中提供的名称将使用函数 stringsim&#xff08;&#xff09; 与存储在类 taxlist 对象中的插槽 taxonNames 中的名称进行比较。 Usage match_names(x, object, ...)## S4 method for signature character,character match…

Java算法 leetcode简单刷题记录10

Java算法 leetcode简单刷题记录10 庆祝一下&#xff1a;大概花费了9天&#xff0c;我把所有leetcode Java 的简单题都刷完了&#xff0c;接下来开始冲刺中等和复杂&#xff1b; 简单题里用到的比较多的是字符串的处理&#xff0c;转换&#xff0c;拆分&#xff0c;替换&#x…

【LeetCode: Z 字形变换 + 模拟】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Redis学习——高级篇②

Redis学习——高级篇② Redis7高级之BigKey&#xff08;二&#xff09; 1.MoreKey案例2.BigKey案例2.1 多大算 BigKey以及它的危害2.2 如何产生、发现、删除 3. bigKey生产调优 Redis7高级之BigKey&#xff08;二&#xff09; 1.MoreKe…

【高效开发工具系列】Java读取Html

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Linux系统安装Nginx

一、Nginx的简介 Nginx是一个高性能的HTTP和反向代理web服务器&#xff0c;是由伊戈尔赛索耶夫为俄罗斯访问量第二站点开发的&#xff0c;因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名&#xff0c;第一个公开版本0.1.0发布于2004年10月4日。 Nginx是一…

C# RichTextBox常用属性、方法学习1

1 字体 Font font1 new Font("宋体", 18); richTextBox1.Font font1; Font font2 new Font("宋体", 10, FontStyle.Underline); richTextBox1.SelectionFont font2; 定义字体&#xff0c;可以带2个参数&#…