• VPP以太网接口模式


    以太网接口结构ethernet_interface_t如下,其成员flags为32bit,高16bit为运行状态标志,低16bit为操作标志。最低bit位表示接口的L2/L3模式设置。第16bit为1表示接口运行在L3模式。

    /* Ethernet interface instance. */
    typedef struct ethernet_interface
    { 
      u32 flags;
      
      /* Top 16 bits for status and bottom 16 bits for set operation */
    #define ETHERNET_INTERFACE_FLAGS_STATUS_MASK  (0xffff0000)
    #define ETHERNET_INTERFACE_FLAGS_SET_OPN_MASK (0x0000ffff)
      
      /* Interface driver/hw is in L3/non-promiscuous mode so packet DMAC would already be filtered */
    #define ETHERNET_INTERFACE_FLAG_STATUS_L3 (1 << 16)
      
      /* Set interface to default L3 mode */
    #define ETHERNET_INTERFACE_FLAG_DEFAULT_L3 0
      
      /* Set interface to accept all packets (promiscuous mode). */
    #define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    物理接口在注册时,例如在VPP插件DPDK中,以太网接口结构成员flags没有进行赋值。函数ethernet_set_flags设置flags的值。

    vnet_eth_register_interface (vnet_main_t *vnm,
                     vnet_eth_interface_registration_t *r)
    {     
      ethernet_main_t *em = ðernet_main;
      ethernet_interface_t *ei; 
      vnet_hw_interface_t *hi;
      u32 hw_if_index;
        
      pool_get (em->interfaces, ei);
      clib_memcpy (&ei->cb, &r->cb, sizeof (vnet_eth_if_callbacks_t));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    修改接口标志

    设置以太网接口的操作标志,高16位的状态标志保持不变。

    ethernet_set_flags (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
    {
      ethernet_main_t *em = ðernet_main;
      vnet_hw_interface_t *hi;
      ethernet_interface_t *ei;
      u32 opn_flags = flags & ETHERNET_INTERFACE_FLAGS_SET_OPN_MASK;
    
      hi = vnet_get_hw_interface (vnm, hw_if_index);
    
      ASSERT (hi->hw_class_index == ethernet_hw_interface_class.index);
    
      ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
    
      /* preserve status bits and update last set operation bits */
      ei->flags = (ei->flags & ETHERNET_INTERFACE_FLAGS_STATUS_MASK) | opn_flags;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    对于DPDK接口,注册的flag_change函数为dpdk_flag_change。如果操作模式设置为L3,检查接口硬件是否支持MAC地址过滤功能,如果不支持,状态不能设置STATUS_L3标志。

    硬件如果支持MAC地址过滤,设置STATUS_L3标志(高16bit)。

    if (ei->cb.flag_change) {
      switch (opn_flags) {	
        case ETHERNET_INTERFACE_FLAG_DEFAULT_L3:
          if (hi->caps & VNET_HW_IF_CAP_MAC_FILTER) {
            if (ei->cb.flag_change (vnm, hi, opn_flags) != ~0) {
              ei->flags |= ETHERNET_INTERFACE_FLAG_STATUS_L3;
              return 0;
            }
            ei->flags &= ~ETHERNET_INTERFACE_FLAG_STATUS_L3;
            return ~0;
          }
          /* fall through */
        case ETHERNET_INTERFACE_FLAG_ACCEPT_ALL:
          ei->flags &= ~ETHERNET_INTERFACE_FLAG_STATUS_L3;
          return ei->cb.flag_change (vnm, hi, opn_flags);
        default:   return ~0;
      }
    }
    return ~0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    如果操作模式设置为L3,关闭网卡混杂模式。否则,开启混杂模式。返回值为混杂模式之前的状态。

    dpdk_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
    {
      dpdk_main_t *dm = &dpdk_main;
      dpdk_device_t *xd = vec_elt_at_index (dm->devices, hi->dev_instance);
      u32 old = (xd->flags & DPDK_DEVICE_FLAG_PROMISC) != 0;
    
      switch (flags) {
        case ETHERNET_INTERFACE_FLAG_DEFAULT_L3:           /* set to L3/non-promisc mode */
          dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_PROMISC, 0);
          break;
        case ETHERNET_INTERFACE_FLAG_ACCEPT_ALL:
          dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_PROMISC, 1);
          break;
        default:  return ~0; 
      }
      if (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) {
          if (xd->flags & DPDK_DEVICE_FLAG_PROMISC)
            rte_eth_promiscuous_enable (xd->port_id);
          else
            rte_eth_promiscuous_disable (xd->port_id);
      }
      return old;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    接口默认模式

    以DPDK接口为例,DPDK接口默认设置为L3操作模式。

    static clib_error_t *
    dpdk_lib_init (dpdk_main_t * dm)
    { 
       /* create interface */
       xd->hw_if_index = vnet_eth_register_interface (vnm, &eir);
       sw = vnet_get_hw_sw_interface (vnm, xd->hw_if_index);
       xd->sw_if_index = sw->sw_if_index;
    
       ethernet_set_flags (vnm, xd->hw_if_index,
               ETHERNET_INTERFACE_FLAG_DEFAULT_L3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    L2/L3模式

    如下命令,设置接口GigabitEthernet0/8/0为L2二层模式,以及设置接口GigabitEthernet0/a/0为L3三层模式。

    vpp# set interface l2 bridge GigabitEthernet0/8/0 200
    vpp#
    vpp# set interface l3 GigabitEthernet0/a/0
    
    • 1
    • 2
    • 3

    函数set_int_l2_mode负责接口模式处理。如果硬件接口的第一个子接口,设置为L2模式,调用ethernet_set_flags,将硬件接口设置为混杂模式(ACCEPT_ALL)。如果硬件接口的最后一个子接口设置为L3模式,将硬件接口的混杂模式关闭(DEFAULT_L3)。

    u32
    set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, )
    {
      /* Adjust count of L2 interfaces */
      hi->l2_if_count += l2_if_adjust;
    
      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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    物流实时数仓:采集通道搭建
    Linux---(五)三大工具yum、vim、gcc/g++
    spring mvc中如何集成logback呢?
    虚拟人三维动画宣传片案例分享 | 广州“五羊”城市文化IP商业体裸眼3D广告影片
    一次服务器被入侵的处理过程分享
    README.md文件使用
    【Android】-- 按钮(复选框CheckBox、开关按钮Switch、单选按钮RadioButton)
    数学建模介绍
    飞利浦zigbee智能灯泡的软硬件设计
    Request Body Search
  • 原文地址:https://blog.csdn.net/sinat_20184565/article/details/132796299