Exemple #1
0
static int dpdk_helper_link_status_get(dpdk_helper_ctx_t *phc) {
  dpdk_events_ctx_t *ec = DPDK_EVENTS_CTX_GET(phc);

  /* get Link Status values from DPDK */
  uint8_t nb_ports = rte_eth_dev_count();
  if (nb_ports == 0) {
    DPDK_CHILD_LOG("dpdkevent-helper: No DPDK ports available. "
                   "Check bound devices to DPDK driver.\n");
    return -ENODEV;
  }
  ec->nb_ports = nb_ports > RTE_MAX_ETHPORTS ? RTE_MAX_ETHPORTS : nb_ports;

  for (int i = 0; i < ec->nb_ports; i++) {
    if (ec->config.link_status.enabled_port_mask & (1 << i)) {
      struct rte_eth_link link;
      ec->link_info[i].read_time = cdtime();
      rte_eth_link_get_nowait(i, &link);
      if ((link.link_status == ETH_LINK_NA) ||
          (link.link_status != ec->link_info[i].link_status)) {
        ec->link_info[i].link_status = link.link_status;
        ec->link_info[i].status_updated = 1;
        DPDK_CHILD_LOG(" === PORT %d Link Status: %s\n", i,
                       link.link_status ? "UP" : "DOWN");
      }
    }
  }

  return 0;
}
Exemple #2
0
static void
app_ports_check_link(void)
{
	uint32_t all_ports_up, i;

	all_ports_up = 1;

	for (i = 0; i < app.n_ports; i++) {
		struct rte_eth_link link;
		uint8_t port;

		port = (uint8_t) app.ports[i];
		memset(&link, 0, sizeof(link));
		rte_eth_link_get_nowait(port, &link);
		RTE_LOG(INFO, USER1, "Port %u (%u Gbps) %s\n",
			port,
			link.link_speed / 1000,
			link.link_status ? "UP" : "DOWN");

		if (link.link_status == 0)
			all_ports_up = 0;
	}

	if (all_ports_up == 0)
		rte_panic("Some NIC ports are DOWN\n");
}
Exemple #3
0
/* Check the link status of all ports in up to 9s, and print them finally */
static void
check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
{
#define CHECK_INTERVAL 100 /* 100ms */
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
	uint16_t portid;
	uint8_t count, all_ports_up, print_flag = 0;
	struct rte_eth_link link;
	uint32_t n_rx_queues, n_tx_queues;

	printf("\nChecking link status");
	fflush(stdout);
	for (count = 0; count <= MAX_CHECK_TIME; count++) {
		all_ports_up = 1;
		for (portid = 0; portid < port_num; portid++) {
			if ((port_mask & (1 << portid)) == 0)
				continue;
			n_rx_queues = app_get_nic_rx_queues_per_port(portid);
			n_tx_queues = app.nic_tx_port_mask[portid];
			if ((n_rx_queues == 0) && (n_tx_queues == 0))
				continue;
			memset(&link, 0, sizeof(link));
			rte_eth_link_get_nowait(portid, &link);
			/* print link status if flag set */
			if (print_flag == 1) {
				if (link.link_status)
					printf(
					"Port%d Link Up - speed %uMbps - %s\n",
						portid, link.link_speed,
				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
					("full-duplex") : ("half-duplex\n"));
				else
					printf("Port %d Link Down\n", portid);
				continue;
			}
			/* clear all_ports_up flag if any link down */
			if (link.link_status == ETH_LINK_DOWN) {
				all_ports_up = 0;
				break;
			}
		}
		/* after finally printing all link status, get out */
		if (print_flag == 1)
			break;

		if (all_ports_up == 0) {
			printf(".");
			fflush(stdout);
			rte_delay_ms(CHECK_INTERVAL);
		}

		/* set the print_flag if all ports up or timeout */
		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
			print_flag = 1;
			printf("done\n");
		}
	}
}
int
tcpreplay_netport_init(struct arguments *args)
{   
    int ret;
    uint8_t rss_key [40];
    struct rte_eth_link link;
    struct rte_eth_dev_info dev_info;
    struct rte_eth_rss_conf rss_conf;
    struct rte_eth_fdir fdir_conf;
    
    /* Retreiving and printing device infos */
    rte_eth_dev_info_get(i, &dev_info);
    printf("Name:%s\n\tDriver name: %s\n\tMax rx queues: %d\n\tMax tx queues: %d\n", dev_info.pci_dev->driver->name,dev_info.driver_name, dev_info.max_rx_queues, dev_info.max_tx_queues);
    printf("\tPCI Adress: %04d:%02d:%02x:%01d\n", dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus, dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function);
    
    /* Configure device with '1' rx queues and 1 tx queue */
    ret = rte_eth_dev_configure(i, 1, 1, &port_conf);
    if (ret < 0) rte_panic("Error configuring the port\n");
    
    /* For each RX queue in each NIC */
    /* Configure rx queue j of current device on current NUMA socket. It takes elements from the mempool */
    ret = rte_eth_rx_queue_setup(i, 0, RX_QUEUE_SZ, rte_socket_id(), &rx_conf, pktmbuf_pool);
    if (ret < 0) FATAL_ERROR("Error configuring receiving queue\n");
    /* Configure mapping [queue] -> [element in stats array] */
    ret = rte_eth_dev_set_rx_queue_stats_mapping    (i, 0, 0);
    if (ret < 0) FATAL_ERROR("Error configuring receiving queue stats\n");
    
    
    /* Configure tx queue of current device on current NUMA socket. Mandatory configuration even if you want only rx packet */
    ret = rte_eth_tx_queue_setup(i, 0, TX_QUEUE_SZ, rte_socket_id(), &tx_conf);
    if (ret < 0) FATAL_ERROR("Error configuring transmitting queue. Errno: %d (%d bad arg, %d no mem)\n", -ret, EINVAL ,ENOMEM);
    
    /* Start device */      
    ret = rte_eth_dev_start(i);
    if (ret < 0) FATAL_ERROR("Cannot start port\n");
    
    /* Enable receipt in promiscuous mode for an Ethernet device */
    rte_eth_promiscuous_enable(i);
    
    /* Print link status */
    rte_eth_link_get_nowait(i, &link);
    if (link.link_status)   printf("\tPort %d Link Up - speed %u Mbps - %s\n", (uint8_t)i, (unsigned)link.link_speed,(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?("full-duplex") : ("half-duplex\n"));
    else            printf("\tPort %d Link Down\n",(uint8_t)i);
    
    /* Print RSS support, not reliable because a NIC could support rss configuration just in rte_eth_dev_configure whithout supporting rte_eth_dev_rss_hash_conf_get*/
    rss_conf.rss_key = rss_key;
    ret = rte_eth_dev_rss_hash_conf_get (i,&rss_conf);
    if (ret == 0) printf("\tDevice supports RSS\n"); else printf("\tDevice DOES NOT support RSS\n");
    
    /* Print Flow director support */
    ret = rte_eth_dev_fdir_get_infos (i, &fdir_conf);
    if (ret == 0) printf("\tDevice supports Flow Director\n"); else printf("\tDevice DOES NOT support Flow Director\n"); 

    if (args)
        return 1;
    return 1;
}
Exemple #5
0
/* Check the link status of all ports in up to 9s, and print them finally */
static void
check_all_ports_link_status()
{
#define CHECK_INTERVAL 100 /* 100ms */
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
    uint8_t portid, count, all_ports_up, print_flag = 0;
    struct rte_eth_link link;

    LOG_RAW(INFO, "\nChecking link status");
    fflush(stdout);
    for (count = 0; count <= MAX_CHECK_TIME; count++) {
        if (sk.force_quit)
            return;
        all_ports_up = 1;

        for (int i = 0; i < sk.nr_ports; i++) {
            if (sk.force_quit)
                return;
            portid = (uint8_t )sk.port_ids[i];
            memset(&link, 0, sizeof(link));
            rte_eth_link_get_nowait(portid, &link);
            /* print link status if flag set */
            if (print_flag == 1) {
                if (link.link_status)
                    LOG_RAW(INFO,
                            "Port %d Link Up - speed %u "
                            "Mbps - %s\n", (uint8_t)portid,
                            (unsigned)link.link_speed,
                            (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
                            ("full-duplex") : ("half-duplex\n"));
                else
                    LOG_RAW(INFO, "Port %d Link Down\n", (uint8_t)portid);
                continue;
            }
            /* clear all_ports_up flag if any link down */
            if (link.link_status == ETH_LINK_DOWN) {
                all_ports_up = 0;
                break;
            }
        }
        /* after finally printing all link status, get out */
        if (print_flag == 1)
            break;

        if (all_ports_up == 0) {
            LOG_RAW(INFO, ".");
            fflush(sk.log_fp);
            rte_delay_ms(CHECK_INTERVAL);
        }

        /* set the print_flag if all ports up or timeout */
        if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
            print_flag = 1;
            LOG_RAW(INFO, "done\n");
        }
    }
}
Exemple #6
0
/**********************************************************************
*@description:
* Check the link status of all ports in up to 9s, and print them finally
*
*@parameters:
* [in]: 
* [in]: 
*
*@return values: 
*
**********************************************************************/
static void odp_check_ports_link_status(uint8_t port_num, uint32_t port_mask)
{
    uint8_t check_interval = 100; /* 100ms */
    uint8_t max_check_time = 90; /* 9s (90 * 100ms) in total */
    uint8_t portid, count, all_ports_up, print_flag = 0;
    struct rte_eth_link link;

    printf("\nChecking link status ");

    for (count = 0; count <= max_check_time; count++) 
    {
    	all_ports_up = 1;
    	for (portid = 0; portid < port_num; portid++) 
       {
    		if ((port_mask & (1 << portid)) == 0)
    			continue;
            
    		memset(&link, 0, sizeof(link));
    		rte_eth_link_get_nowait(portid, &link);
    		/* print link status if flag set */
    		if (print_flag == 1) 
              {
    			if (link.link_status)
    				printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid,
    					(unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n"));
    			else
    				printf("Port %d Link Down\n", (uint8_t)portid);
                
    			continue;
    		}
    		/* clear all_ports_up flag if any link down */
    		if (link.link_status == 0) 
              {
    			all_ports_up = 0;
    			break;
    		}
    	}
        
    	/* after finally printing all link status, get out */
    	if (print_flag == 1)
    		break;

    	if (all_ports_up == 0) 
       {
            printf(".");
            rte_delay_ms(check_interval);
    	}

    	/* set the print_flag if all ports up or timeout */
    	if (all_ports_up == 1 || count == (max_check_time - 1)) 
       {
            print_flag = 1;
            printf("done\n");
    	}
    }
}
Exemple #7
0
int
vfd_mlx5_set_qos_pf(uint16_t port_id, tc_class_t **tc_config, uint8_t ntcs)
{
	char ifname[IF_NAMESIZE];
	char cmd[256] = "";
	struct mlx5_tc_cfg tc_cfg[MAX_TCS];
	struct rte_eth_link link;
	int i, ret;

	if (vfd_mlx5_get_ifname(port_id, ifname))
		return -1;

	if (ntcs != 8) {
		printf("mlx5 devices don't support 4 TC configuration\n");
		return -2;
	}

	memset(tc_cfg, 0, sizeof(tc_cfg));

	rte_eth_link_get_nowait(port_id, &link);

	for(i=0; i< ntcs; i++) {
		strcpy(tc_cfg[i].policy, (tc_config[i]->flags & TCF_LNK_STRICTP) ? "strict" : "ets");
		tc_cfg[i].min_bw = (tc_config[i]->flags & TCF_LNK_STRICTP) ? 0 : tc_config[i]->min_bw;
		if (tc_config[i]->max_bw < 100) {
			tc_cfg[i].max_bw = (tc_config[i]->max_bw * link.link_speed) / 100;
			if (tc_cfg[i].max_bw < 1000)
				tc_cfg[i].max_bw = 1000;

			//move to Gbps
			tc_cfg[i].max_bw =  tc_cfg[i].max_bw / 1000;
		}
	}
		

	sprintf(cmd, "mlnx_qos -i %s -s %s,%s,%s,%s,%s,%s,%s,%s -t %d,%d,%d,%d,%d,%d,%d,%d", ifname, tc_cfg[0].policy, tc_cfg[1].policy,
			tc_cfg[2].policy, tc_cfg[3].policy, tc_cfg[4].policy, tc_cfg[5].policy, tc_cfg[6].policy, tc_cfg[7].policy,
			tc_cfg[0].min_bw, tc_cfg[1].min_bw, tc_cfg[2].min_bw, tc_cfg[3].min_bw, tc_cfg[4].min_bw, tc_cfg[5].min_bw,
			tc_cfg[6].min_bw, tc_cfg[7].min_bw);

	ret = system(cmd);

	//set rate limiters
	
	sprintf(cmd, "mlnx_qos -i %s -r %d,%d,%d,%d,%d,%d,%d,%d", ifname, tc_cfg[0].max_bw, tc_cfg[1].max_bw, tc_cfg[2].max_bw,
				tc_cfg[3].max_bw, tc_cfg[4].max_bw, tc_cfg[5].max_bw, tc_cfg[6].max_bw, tc_cfg[7].max_bw);

	ret = system(cmd);

	if (ret < 0) {
	//	printf("cmd exec returned %d\n", ret);
	}

	return 0;
}
Exemple #8
0
void 
rw_piot_get_link_info(rw_piot_api_handle_t api_handle, rw_piot_link_info_t *eth_link_info)
{
  rw_piot_device_t *rw_piot_dev = RWPIOT_GET_DEVICE(api_handle);
  ASSERT(RWPIOT_VALID_DEVICE(rw_piot_dev));
  if (NULL == rw_piot_dev || NULL == eth_link_info) {
    RW_PIOT_LOG(RTE_LOG_ERR, "PIOT Could not find device by handle or invalid input param\n");
    return;
  }
  rte_eth_link_get_nowait(rw_piot_dev->rte_port_id, eth_link_info);
  return;
}
Exemple #9
0
/* Check the link status of all ports in up to 9s, and print them finally */
static void
check_all_ports_link_status(uint8_t port_num)
{
#define CHECK_INTERVAL 100 /* 100ms */
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
    uint8_t portid, count, all_ports_up, print_flag = 0;
    struct rte_eth_link link;

    printf("\nChecking link status");
    fflush(stdout);
    rte_delay_ms(15000);
    for (count = 0; count <= MAX_CHECK_TIME; count++) {
        all_ports_up = 1;
        for (portid = 0; portid < port_num; portid++) {
            memset(&link, 0, sizeof(link));
            rte_eth_link_get_nowait(portid, &link);
            /* print link status if flag set */
            if (print_flag == 1) {
                if (link.link_status)
                    printf("Port %d Link Up - speed %u "
                           "Mbps - %s\n", (uint8_t)portid,
                           (unsigned)link.link_speed,
                           (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
                           ("full-duplex") : ("half-duplex\n"));
                else
                    printf("Port %d Link Down\n",
                           (uint8_t)portid);
                continue;
            }
            /* clear all_ports_up flag if any link down */
            if (link.link_status == 0) {
                all_ports_up = 0;
                break;
            }
        }
        /* after finally printing all link status, get out */
        if (print_flag == 1)
            break;

        if (all_ports_up == 0) {
            printf(".");
            fflush(stdout);
            rte_delay_ms(CHECK_INTERVAL);
        }

        /* set the print_flag if all ports up or timeout */
        if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
            print_flag = 1;
            printf("done\n");
        }
    }
}
Exemple #10
0
int uhd_dpdk_port_link_status(unsigned int portid)
{
    if (!ctx)
        return -ENODEV;

    struct uhd_dpdk_port *p = find_port(portid);
    if (p) {
        struct rte_eth_link link;
        rte_eth_link_get_nowait(p->id, &link);
        return link.link_status;
    }
    return -ENODEV;
}
Exemple #11
0
/**
 * @brief           Get device link state
 * 
 * @param devId     uint8_t, ID of DPDK device
 * @param link      EthLinkState_t*, pointer to buffer where device link state will be stored
 * 
 * @return          true if success and false otherwice
 */
bool DPDKAdapter::getDevLinkState(uint8_t devId, EthLinkState_t* link)
{
    if(devId > RTE_MAX_ETHPORTS)
    {
        qCritical("Device ID is out of range");
        return false;
    }
    
    memset(link, 0, sizeof(EthLinkState_t));

    rte_eth_link_get_nowait(devId, link);

    return true;
}
Exemple #12
0
static void udpi_ports_check_link(void)
{
	struct rte_eth_link link;
	uint32_t port_id;

	for (port_id=0; port_id<udpi.n_ports; port_id++)
	{
		memset(&link, 0, sizeof(struct rte_eth_link));
		rte_eth_link_get_nowait(port_id, &link);
		RTE_LOG(INFO, PORT, "Port %u (%u Gbps) %s\n",
			port_id, link.link_speed / 1000, link.link_status ? "UP":"DOWN");
	}
		
	return;
}
void
port_infos_display(struct cmdline *cl, portid_t port_id)
{
	struct ether_addr mac_addr;
	struct rte_eth_link link;
	int vlan_offload;
	static const char *info_border = "=====================";

	rte_eth_link_get_nowait(port_id, &link);
	cmdline_printf(cl, "\n%s Infos for port %-2d %s\n", info_border,
		       port_id, info_border);
	rte_eth_macaddr_get(port_id, &mac_addr);
	print_ethaddr(cl, "MAC address: ", &mac_addr);

	cmdline_printf(cl, "\nLink status: %s\n",
		       (link.link_status) ? ("up") : ("down"));
	cmdline_printf(cl, "Link speed: %u Mbps\n", (unsigned)link.link_speed);
	cmdline_printf(cl, "Link duplex: %s\n",
		       (link.link_duplex == ETH_LINK_FULL_DUPLEX)
			   ? ("full-duplex")
			   : ("half-duplex"));
	cmdline_printf(cl, "Promiscuous mode: %s\n",
		       rte_eth_promiscuous_get(port_id) ? "enabled"
							: "disabled");
	cmdline_printf(cl, "Allmulticast mode: %s\n",
		       rte_eth_allmulticast_get(port_id) ? "enabled"
							 : "disabled");

	vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
	if (vlan_offload >= 0) {
		cmdline_printf(cl, "VLAN offload: \n");
		if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD)
			cmdline_printf(cl, "  strip on \n");
		else
			cmdline_printf(cl, "  strip off \n");

		if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD)
			cmdline_printf(cl, "  filter on \n");
		else
			cmdline_printf(cl, "  filter off \n");

		if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)
			cmdline_printf(cl, "  qinq(extend) on \n");
		else
			cmdline_printf(cl, "  qinq(extend) off \n");
	}
}
Exemple #14
0
int linkStatusGet(const char* device)
{
    int deviceId = 0;
    struct rte_eth_link link;

    if (device == NULL)
    {
        snprintf (errbuf_g, PCAP_ERRBUF_SIZE, "Invalid parameter");
        return DPDKPCAP_FAILURE;
    }

    deviceId = findDevice(device, errbuf_g);

    rte_eth_link_get_nowait(deviceId, &link);

    return link.link_status;
}
Exemple #15
0
static void
lsi_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param)
{
    struct rte_eth_link link;

    RTE_SET_USED(param);

    printf("\n\nIn registered callback...\n");
    printf("Event type: %s\n", type == RTE_ETH_EVENT_INTR_LSC ? "LSC interrupt" : "unknown event");
    rte_eth_link_get_nowait(port_id, &link);
    if (link.link_status) {
        printf("Port %d Link Up - speed %u Mbps - %s\n\n",
                port_id, (unsigned)link.link_speed,
            (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
                ("full-duplex") : ("half-duplex"));
    } else
        printf("Port %d Link Down\n\n", port_id);
}
void init_port(int port_id)
{
	struct rte_eth_dev_info dev_info;
	int ret;
	struct rte_eth_link link;
	
	rte_eth_dev_info_get(port_id, &dev_info);
	printf("Name:%s\n\tDriver name: %s\n\tMax rx queues: %d\n\tMax tx queues: %d\n", dev_info.pci_dev->driver->name,dev_info.driver_name, dev_info.max_rx_queues, dev_info.max_tx_queues);
	printf("\tPCI Adress: %04d:%02d:%02x:%01d\n", dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus, dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function);

	ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
	if (ret < 0) 
		rte_panic("Error configuring the port\n");

	ret = rte_eth_rx_queue_setup(port_id, 0, RX_QUEUE_SZ, rte_socket_id(), &rx_conf, pktmbuf_pool);
	if (ret < 0) 
		FATAL_ERROR("Error configuring receiving queue= %d\n", ret);

	// TODO: Need to check whether it is supported in the VMXNET
	/*ret = rte_eth_dev_set_rx_queue_stats_mapping(port_id, 0, 0);       
	if (ret < 0) 
		FATAL_ERROR("Error configuring receiving queue stats= %d [ENOTSUP= %d]\n", ret, ENOTSUP); */

	ret = rte_eth_tx_queue_setup(port_id, 0, TX_QUEUE_SZ, rte_socket_id(), &tx_conf);
	if (ret < 0) 
		FATAL_ERROR("Error configuring transmitting queue. Errno: %d (%d bad arg, %d no mem)\n", -ret, EINVAL ,ENOMEM);

	/* Start device */    
	ret = rte_eth_dev_start(port_id);
	if (ret < 0) 
		FATAL_ERROR("Cannot start port\n");

	/* Enable receipt in promiscuous mode for an Ethernet device */
	//rte_eth_promiscuous_enable(port_id);

	/* Print link status */
	rte_eth_link_get_nowait(port_id, &link);                
	if (link.link_status)   
		printf("\tPort %d Link Up - speed %u Mbps - %s\n", (uint8_t)port_id, (unsigned)link.link_speed,(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?("full-duplex") : ("half-duplex\n"));
	else
		printf("\tPort %d Link Down\n",(uint8_t)port_id);
}
Exemple #17
0
lagopus_result_t
update_port_link_status(struct port *port) {
  struct rte_eth_link link;
  uint8_t portid;
  bool changed = false;

  portid = (uint8_t)port->ifindex;
  /* ofp_port.config is configured by the controller. */

  /* other port status. */
  /* OFPPF_* for OpenFlow 1.3 */
  rte_eth_link_get_nowait(portid, &link);
  switch (link.link_speed) {
    case ETH_LINK_SPEED_10:
      port->ofp_port.curr_speed = 10* 1000;
      port->ofp_port.curr = OFPPF_10MB_FD;
      break;
    case ETH_LINK_SPEED_100:
      port->ofp_port.curr_speed = 100 * 1000;
      port->ofp_port.curr = OFPPF_100MB_FD;
      break;
    case ETH_LINK_SPEED_1000:
      port->ofp_port.curr_speed = 1000 * 1000;
      port->ofp_port.curr = OFPPF_1GB_FD;
      break;
    case ETH_LINK_SPEED_10000:
      port->ofp_port.curr_speed = 10000 * 1000;
      port->ofp_port.curr = OFPPF_10GB_FD;
      break;
    default:
      port->ofp_port.curr_speed = 0;
      port->ofp_port.curr = OFPPF_OTHER;
      break;
  }
  if (port->ofp_port.curr_speed != 0 &&
      link.link_duplex != ETH_LINK_FULL_DUPLEX) {
    port->ofp_port.curr >>= 1;
  }
static int
__eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
{
	struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev;
	struct bond_dev_private *internals;
	struct bond_dev_private *temp_internals;
	struct rte_eth_link link_props;
	struct rte_eth_dev_info dev_info;

	int i, j;

	if (valid_slave_port_id(slave_port_id) != 0)
		return -1;

	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
	internals = bonded_eth_dev->data->dev_private;

	/* Verify that new slave device is not already a slave of another
	 * bonded device */
	for (i = rte_eth_dev_count()-1; i >= 0; i--) {
		if (valid_bonded_ethdev(&rte_eth_devices[i]) == 0) {
			temp_internals = rte_eth_devices[i].data->dev_private;

			for (j = 0; j < temp_internals->slave_count; j++) {
				/* Device already a slave of a bonded device */
				if (temp_internals->slaves[j].port_id == slave_port_id) {
					RTE_BOND_LOG(ERR, "Slave port %d is already a slave",
							slave_port_id);
					return -1;
				}
			}
		}
	}

	slave_eth_dev = &rte_eth_devices[slave_port_id];

	/* Add slave details to bonded device */
	slave_add(internals, slave_eth_dev);

	memset(&dev_info, 0, sizeof(dev_info));
	rte_eth_dev_info_get(slave_port_id, &dev_info);

	if (internals->slave_count < 1) {
		/* if MAC is not user defined then use MAC of first slave add to
		 * bonded device */
		if (!internals->user_defined_mac)
			mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs);

		/* Inherit eth dev link properties from first slave */
		link_properties_set(bonded_eth_dev,
				&(slave_eth_dev->data->dev_link));

		/* Make primary slave */
		internals->primary_port = slave_port_id;

		/* Take the first dev's offload capabilities */
		internals->rx_offload_capa = dev_info.rx_offload_capa;
		internals->tx_offload_capa = dev_info.tx_offload_capa;

	} else {
		/* Check slave link properties are supported if props are set,
		 * all slaves must be the same */
		if (internals->link_props_set) {
			if (link_properties_valid(&(bonded_eth_dev->data->dev_link),
									  &(slave_eth_dev->data->dev_link))) {
				RTE_BOND_LOG(ERR,
						"Slave port %d link speed/duplex not supported",
						slave_port_id);
				return -1;
			}
		} else {
			link_properties_set(bonded_eth_dev,
					&(slave_eth_dev->data->dev_link));
		}
		internals->rx_offload_capa &= dev_info.rx_offload_capa;
		internals->tx_offload_capa &= dev_info.tx_offload_capa;
	}

	internals->slave_count++;

	/* Update all slave devices MACs*/
	mac_address_slaves_update(bonded_eth_dev);

	if (bonded_eth_dev->data->dev_started) {
		if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) {
			RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d",
					slave_port_id);
			return -1;
		}
	}

	/* Register link status change callback with bonded device pointer as
	 * argument*/
	rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC,
			bond_ethdev_lsc_event_callback, &bonded_eth_dev->data->port_id);

	/* If bonded device is started then we can add the slave to our active
	 * slave array */
	if (bonded_eth_dev->data->dev_started) {
		rte_eth_link_get_nowait(slave_port_id, &link_props);

		 if (link_props.link_status == 1)
			activate_slave(bonded_eth_dev, slave_port_id);
	}
	return 0;

}
static int
__eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id)
{
	struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev;
	struct bond_dev_private *internals;
	struct rte_eth_link link_props;
	struct rte_eth_dev_info dev_info;

	if (valid_slave_port_id(slave_port_id) != 0)
		return -1;

	bonded_eth_dev = &rte_eth_devices[bonded_port_id];
	internals = bonded_eth_dev->data->dev_private;

	slave_eth_dev = &rte_eth_devices[slave_port_id];
	if (slave_eth_dev->data->dev_flags & RTE_ETH_DEV_BONDED_SLAVE) {
		RTE_BOND_LOG(ERR, "Slave device is already a slave of a bonded device");
		return -1;
	}

	/* Add slave details to bonded device */
	slave_eth_dev->data->dev_flags |= RTE_ETH_DEV_BONDED_SLAVE;

	rte_eth_dev_info_get(slave_port_id, &dev_info);
	if (dev_info.max_rx_pktlen < internals->max_rx_pktlen) {
		RTE_BOND_LOG(ERR, "Slave (port %u) max_rx_pktlen too small",
			     slave_port_id);
		return -1;
	}

	slave_add(internals, slave_eth_dev);

	/* We need to store slaves reta_size to be able to synchronize RETA for all
	 * slave devices even if its sizes are different.
	 */
	internals->slaves[internals->slave_count].reta_size = dev_info.reta_size;

	if (internals->slave_count < 1) {
		/* if MAC is not user defined then use MAC of first slave add to
		 * bonded device */
		if (!internals->user_defined_mac)
			mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs);

		/* Inherit eth dev link properties from first slave */
		link_properties_set(bonded_eth_dev,
				&(slave_eth_dev->data->dev_link));

		/* Make primary slave */
		internals->primary_port = slave_port_id;
		internals->current_primary_port = slave_port_id;

		/* Inherit queues settings from first slave */
		internals->nb_rx_queues = slave_eth_dev->data->nb_rx_queues;
		internals->nb_tx_queues = slave_eth_dev->data->nb_tx_queues;

		internals->reta_size = dev_info.reta_size;

		/* Take the first dev's offload capabilities */
		internals->rx_offload_capa = dev_info.rx_offload_capa;
		internals->tx_offload_capa = dev_info.tx_offload_capa;
		internals->flow_type_rss_offloads = dev_info.flow_type_rss_offloads;

		/* Inherit first slave's max rx packet size */
		internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen;

	} else {
		internals->rx_offload_capa &= dev_info.rx_offload_capa;
		internals->tx_offload_capa &= dev_info.tx_offload_capa;
		internals->flow_type_rss_offloads &= dev_info.flow_type_rss_offloads;

		/* RETA size is GCD of all slaves RETA sizes, so, if all sizes will be
		 * the power of 2, the lower one is GCD
		 */
		if (internals->reta_size > dev_info.reta_size)
			internals->reta_size = dev_info.reta_size;

		if (!internals->max_rx_pktlen &&
		    dev_info.max_rx_pktlen < internals->candidate_max_rx_pktlen)
			internals->candidate_max_rx_pktlen = dev_info.max_rx_pktlen;
	}

	bonded_eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf &=
			internals->flow_type_rss_offloads;

	internals->slave_count++;

	/* Update all slave devices MACs*/
	mac_address_slaves_update(bonded_eth_dev);

	if (bonded_eth_dev->data->dev_started) {
		if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) {
			slave_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDED_SLAVE);
			RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d",
					slave_port_id);
			return -1;
		}
	}

	/* Register link status change callback with bonded device pointer as
	 * argument*/
	rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC,
			bond_ethdev_lsc_event_callback, &bonded_eth_dev->data->port_id);

	/* If bonded device is started then we can add the slave to our active
	 * slave array */
	if (bonded_eth_dev->data->dev_started) {
		rte_eth_link_get_nowait(slave_port_id, &link_props);

		 if (link_props.link_status == ETH_LINK_UP) {
			if (internals->active_slave_count == 0 &&
			    !internals->user_defined_primary_port)
				bond_ethdev_primary_set(internals,
							slave_port_id);

			if (find_slave_by_id(internals->active_slaves,
					     internals->active_slave_count,
					     slave_port_id) == internals->active_slave_count)
				activate_slave(bonded_eth_dev, slave_port_id);
		}
	}

	slave_vlan_filter_set(bonded_port_id, slave_port_id);

	return 0;

}