LCP插件linux-cp-xc-ip4节点
创始人
2025-05-30 21:49:55

如下命令创建LCP接口对,VPP物理接口eth0,对应linux接口host-eth0。LCP插件创建了virtio类型的tap1接口,用于和host-eth0连通。

vpp# lcp create eth0 host-if host-eth0
vpp#
vpp#
vpp# show lcp
itf-pair: [0] eth0 tap1 host-eth0 10 type tap
vpp#
vpp#
vpp# show interfaceName               Idx    State  MTU (L3/IP4/IP6/MPLS)     Counter          Count
eth0                              1     down         9000/0/0/0
tap1                              2      up       1920099631/0/0/0

如下定义节点linux-cp-xc-ip4,类型VLIB_NODE_TYPE_INTERNAL。节点属于ip-unicast/ip4-multicast 特性arc。用于处理linux发往VPP的流量。

VLIB_REGISTER_NODE (lcp_xc_ip4) = { .name = "linux-cp-xc-ip4",.vector_size = sizeof (u32),.format_trace = format_lcp_xc_trace,.type = VLIB_NODE_TYPE_INTERNAL,.sibling_of = "ip4-rewrite" };VNET_FEATURE_INIT (lcp_xc_ip4_ucast_node, static) = {.arc_name = "ip4-unicast",.node_name = "linux-cp-xc-ip4",
};
VNET_FEATURE_INIT (lcp_xc_ip4_mcast_node, static) = {.arc_name = "ip4-multicast",.node_name = "linux-cp-xc-ip4",
};

节点处理函数lcp_xc_ip4如下,实际处理由函数lcp_xc_inline完成。

VLIB_NODE_FN (lcp_xc_ip4)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{return (lcp_xc_inline (vm, node, frame, AF_IP4));
}

函数lcp_xc_inline用户处理有linux接收到的IPv4或者IPv6报文。根据参数af,选择对应的ip_lookup_main_t结构。

static_always_inline u32
lcp_xc_inline (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame,ip_address_family_t af)
{u32 n_left_from, *from, *to_next, n_left_to_next;lcp_xc_next_t next_index;ip_lookup_main_t *lm;next_index = 0;n_left_from = frame->n_vectors;from = vlib_frame_vector_args (frame);if (AF_IP4 == af)lm = &ip4_main.lookup_main;elselm = &ip6_main.lookup_main;

开始时,并不能确定处理报文的下一个节点,假定下一个节点索引为0,vlib_get_next_frame函数获取此节点当前可接收的向量起始位置(to_next)和数量(n_left_to_next)。随后,如果报文的下一节点索引不是0,将进行确认和修复。

  while (n_left_from > 0){vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);while (n_left_from > 0 && n_left_to_next > 0){const ethernet_header_t *eth;const lcp_itf_pair_t *lip;u32 next0, bi0, lipi, ai;vlib_buffer_t *b0;const ip_adjacency_t *adj;bi0 = to_next[0] = from[0];from += 1;to_next += 1;n_left_from -= 1;n_left_to_next -= 1;

根据接收到报文的接口索引(tap1索引2),找到LCP接口对,进而找到对应的VPP物理接口(lip_phy_sw_if_index为eth0),此接口为报文的出接口(VLIB_TX)。

      b0 = vlib_get_buffer (vm, bi0);lipi = lcp_itf_pair_find_by_host (vnet_buffer (b0)->sw_if_index[VLIB_RX]);lip = lcp_itf_pair_get (lipi);vnet_buffer (b0)->sw_if_index[VLIB_TX] = lip->lip_phy_sw_if_index;

根据报文的MAC层数据信息,和出接口,找到邻居索引,进而找到ip_adjacency_t结构。其中保存的下一个节点信息next0,为报文要发往的下一个节点(如果与next_index不相等,说明之前假设的有误)。

      vlib_buffer_advance (b0, -lip->lip_rewrite_len);eth = vlib_buffer_get_current (b0);ai = ADJ_INDEX_INVALID;if (!ethernet_address_cast (eth->dst_address))ai = lcp_adj_lkup ((u8 *) eth, lip->lip_rewrite_len,vnet_buffer (b0)->sw_if_index[VLIB_TX]);if (ai == ADJ_INDEX_INVALID)ai = lip->lip_phy_adjs.adj_index[af];adj = adj_get (ai);vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ai;next0 = adj->rewrite_header.next_index;vnet_buffer (b0)->ip.save_rewrite_length = lip->lip_rewrite_len;if (PREDICT_FALSE (adj->rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))vnet_feature_arc_start_w_cfg_index (lm->output_feature_arc_index,vnet_buffer (b0)->sw_if_index[VLIB_TX], &next0, b0, adj->ia_cfg_index);

如果开启了trace命令,填充trace信息,包括VPP出接口索引和邻居索引。

      if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED))) {lcp_xc_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));t->phy_sw_if_index = lip->lip_phy_sw_if_index;t->adj_index = vnet_buffer (b0)->ip.adj_index[VLIB_TX];}

函数vlib_validate_buffer_enqueue_x1根据正确的下一跳节点next0,进行修正。

      vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,n_left_to_next, bi0, next0);}vlib_put_next_frame (vm, node, next_index, n_left_to_next);}return frame->n_vectors;

如果next0与next_index相等,表明while循环开始时使用的节点索引是正确的,不需要修正。否则,还原错误使用的节点(或者,下一节点改变了),随后,根据正确下一节点索引,获取其可用的向量起始位置,和可用的数量。将报文索引bi0赋值到下一节点第一个可用位置,并增加1,可用的位置数量减少1。

#define vlib_validate_buffer_enqueue_x1(vm,node,next_index,to_next,n_left_to_next,bi0,next0) \
do {                                    \ASSERT (bi0 != 0);                            \ if (PREDICT_FALSE (next0 != next_index))              \{                                   \vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1);   \next_index = next0;                       \vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); \\to_next[0] = bi0;                         \to_next += 1;                         \n_left_to_next -= 1;                      \}                                   \
} while (0) 

TRACE信息

节点virtio-input由tap1接收到报文,经由节点ethernet-input和ip-input,到达节点linux-cp-xc-ip4,随后由VPP物理接口eth0的发送函数发送出去。

vpp# show trace 
------------------- Start of thread 1 vpp_wk_0 -------------------
Packet 100:36:17:622826: virtio-inputvirtio: hw_if_index 2 next-index 4 vring 0 len 98hdr: flags 0x00 gso_type 0x00 hdr_len 0 gso_size 0 csum_start 0 csum_offset 0 num_buffers 1
00:36:17:622828: ethernet-inputIP4: 00:60:e0:6f:9c:e5 -> 6c:24:08:6b:e3:3d
00:36:17:622829: ip4-inputICMP: 17.1.2.1 -> 17.1.2.2tos 0x00, ttl 64, length 84, checksum 0x9be8 dscp CS0 ecn NON_ECNfragment id 0x78bc, flags DONT_FRAGMENTICMP echo_request checksum 0x6897 id 13712
00:36:17:622831: linux-cp-xc-ip4lcp-xc: itf:1 adj:4
00:36:17:622832: eth0-outputeth0 IP4: 00:60:e0:6f:9c:e5 -> 6c:24:08:6b:e3:3dICMP: 17.1.2.1 -> 17.1.2.2tos 0x00, ttl 64, length 84, checksum 0x9be8 dscp CS0 ecn NON_ECNfragment id 0x78bc, flags DONT_FRAGMENTICMP echo_request checksum 0x6897 id 13712
00:36:17:622833: eth0-txeth0 tx queue 1buffer 0x9cb1e: current data 0, length 98, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x1000000l2-hdr-offset 0 l3-hdr-offset 14 PKT MBUF: port 65535, nb_segs 1, pkt_len 98buf_len 2176, data_len 98, ol_flags 0x0, data_off 128, phys_addr 0x8852c800packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0 rss 0x0 fdir.hi 0x0 fdir.lo 0x0IP4: 00:60:e0:6f:9c:e5 -> 6c:24:08:6b:e3:3dICMP: 17.1.2.1 -> 17.1.2.2tos 0x00, ttl 64, length 84, checksum 0x9be8 dscp CS0 ecn NON_ECNfragment id 0x78bc, flags DONT_FRAGMENTICMP echo_request checksum 0x6897 id 13712

相关内容

热门资讯

实测讲解“白金岛麻将圈到底是不... 您好:白金岛麻将圈这款游戏可以开挂,确实是有挂的,需要了解加客服微信【4282891】很多玩家在这款...
我来教教您“极酷牛牛有挂吗”(... 我来教教您“极酷牛牛有挂吗”(太坑了原来有挂)亲,极酷牛牛这个游戏其实有挂的,确实是有挂的,需要了解...
今日重磅消息“奔驰宝马开挂器”... 有 亲,根据资深记者爆料奔驰宝马是可以开挂的,确实有挂(咨询软件无需打开...
我来教教您“宝马互娱辅助软件”... 您好:宝马互娱这款游戏可以开挂,确实是有挂的,需要了解加客服微信【9752949】很多玩家在这款游戏...
我来教教您“,850棋牌到底是... 有 亲,根据资深记者爆料,850棋牌是可以开挂的,确实有挂(咨询软件无需...