As well as connections to a physical network interface the netmap API also supports connections to two different types for virtual ports, VALE switch ports and netmap pipe ports. VALE is a virtual switch implemented in the netmap kernel module, it works as a learning bridge and is designed to be used for connections between virtual machines. netmap pipes connect two virtual netmap ports with a crossover connection, they can be used in a setup where a master process works as a dispatcher towards slave processes.
Virtual netmap ports are given a dummy MAC address from locally administered MAC address range (02:00:00:00:00:XX). Reviewed-by: Petri Savolainen <[email protected]> Signed-off-by: Matias Elo <[email protected]> Suggested-by: Stuart Haslam <[email protected]> --- platform/linux-generic/include/odp_packet_netmap.h | 1 + platform/linux-generic/pktio/netmap.c | 70 +++++++++++++++++++--- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/platform/linux-generic/include/odp_packet_netmap.h b/platform/linux-generic/include/odp_packet_netmap.h index 6338c36..ebb0f8d 100644 --- a/platform/linux-generic/include/odp_packet_netmap.h +++ b/platform/linux-generic/include/odp_packet_netmap.h @@ -45,6 +45,7 @@ typedef struct { unsigned char if_mac[ETH_ALEN]; /**< eth mac address */ char nm_name[IF_NAMESIZE + 7]; /**< netmap:<ifname> */ char if_name[IF_NAMESIZE]; /**< interface name used in ioctl */ + odp_bool_t is_virtual; /**< nm virtual port (VALE/pipe) */ odp_pktio_capability_t capa; /**< interface capabilities */ unsigned cur_rx_queue; /**< current pktin queue */ uint32_t num_rx_rings; /**< number of nm rx rings */ diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c index 34ca920..5828669 100644 --- a/platform/linux-generic/pktio/netmap.c +++ b/platform/linux-generic/pktio/netmap.c @@ -210,6 +210,9 @@ static int netmap_close(pktio_entry_t *pktio_entry) static int netmap_link_status(pktio_entry_t *pktio_entry) { + if (pktio_entry->s.pkt_nm.is_virtual) + return 1; + return link_status_fd(pktio_entry->s.pkt_nm.sockfd, pktio_entry->s.pkt_nm.if_name); } @@ -238,7 +241,8 @@ static inline int netmap_wait_for_link(pktio_entry_t *pktio_entry) * until the opposing end's interface comes back up again. In * this case without the additional sleep pktio validation * tests fail. */ - sleep(1); + if (!pktio_entry->s.pkt_nm.is_virtual) + sleep(1); if (ret == 1) return 1; } @@ -246,6 +250,30 @@ static inline int netmap_wait_for_link(pktio_entry_t *pktio_entry) return 0; } +/** + * Open a netmap interface + * + * In addition to standard interfaces (with or without modified netmap drivers) + * virtual VALE and pipe interfaces are also supported. These can be used for + * example for testing packet IO functionality without any physical interfaces. + * + * To use virtual interfaces the 'netdev' device name has to begin with 'vale' + * prefix. A valid VALE device name would be e.g. 'vale0'. Pipe device names + * have to include also '{NN' (master) or '}NN' (slave) suffix. A valid pipe + * master would be e.g. 'vale0{0' and a slave to the same pipe 'vale0}0'. + * + * Netmap requires standard interface names to begin with 'netmap:' prefix. + * netmap_open() adds the prefix if it is missing. Virtual interfaces don't + * require the 'netmap:' prefix. + * + * @param id Packet IO handle + * @param pktio_entry Packet IO entry + * @param netdev Packet IO device name + * @param pool Default pool from which to allocate storage for packets + * + * @retval 0 on success + * @retval <0 on failure + */ static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, const char *netdev, odp_pool_t pool) { @@ -278,9 +306,13 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, odp_buffer_pool_tailroom(pool); /* allow interface to be opened with or without the 'netmap:' prefix */ + prefix = "netmap:"; if (strncmp(netdev, "netmap:", 7) == 0) netdev += 7; - prefix = "netmap:"; + if (strncmp(netdev, "vale", 4) == 0) { + pkt_nm->is_virtual = 1; + prefix = ""; + } snprintf(pkt_nm->nm_name, sizeof(pkt_nm->nm_name), "%s%s", prefix, netdev); @@ -317,6 +349,24 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, buf_size = ring->nr_buf_size; nm_close(desc); + for (i = 0; i < PKTIO_MAX_QUEUES; i++) { + odp_ticketlock_init(&pkt_nm->rx_desc_ring[i].s.lock); + odp_ticketlock_init(&pkt_nm->tx_desc_ring[i].s.lock); + } + + if (pkt_nm->is_virtual) { + static unsigned mac; + + pkt_nm->capa.max_input_queues = 1; + pkt_nm->mtu = buf_size; + pktio_entry->s.stats_type = STATS_UNSUPPORTED; + /* Set MAC address for virtual interface */ + pkt_nm->if_mac[0] = 0x2; + pkt_nm->if_mac[5] = ++mac; + + return 0; + } + sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { ODP_ERR("Cannot get device control socket\n"); @@ -350,11 +400,6 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, if (err) goto error; - for (i = 0; i < PKTIO_MAX_QUEUES; i++) { - odp_ticketlock_init(&pkt_nm->rx_desc_ring[i].s.lock); - odp_ticketlock_init(&pkt_nm->tx_desc_ring[i].s.lock); - } - /* netmap uses only ethtool to get statistics counters */ err = ethtool_stats_get_fd(pktio_entry->s.pkt_nm.sockfd, pkt_nm->if_name, &cur_stats); @@ -430,6 +475,7 @@ static int netmap_start(pktio_entry_t *pktio_entry) pktio_entry->s.num_out_queue, pktio_entry->s.num_out_queue); + memset(&base_desc, 0, sizeof(struct nm_desc)); base_desc.self = &base_desc; base_desc.mem = NULL; memcpy(base_desc.req.nr_name, pkt_nm->if_name, sizeof(pkt_nm->if_name)); @@ -474,7 +520,7 @@ static int netmap_start(pktio_entry_t *pktio_entry) /* Open tx descriptors */ desc_ring = pkt_nm->tx_desc_ring; flags = NM_OPEN_IFNAME | NM_OPEN_NO_MMAP; - base_desc.req.nr_flags &= !NR_REG_ALL_NIC; + base_desc.req.nr_flags &= ~NR_REG_ALL_NIC; base_desc.req.nr_flags |= NR_REG_ONE_NIC; for (i = 0; i < pktio_entry->s.num_out_queue; i++) { for (j = desc_ring[i].s.first; j <= desc_ring[i].s.last; j++) { @@ -774,12 +820,20 @@ static int netmap_mtu_get(pktio_entry_t *pktio_entry) static int netmap_promisc_mode_set(pktio_entry_t *pktio_entry, odp_bool_t enable) { + if (pktio_entry->s.pkt_nm.is_virtual) { + __odp_errno = ENOTSUP; + return -1; + } + return promisc_mode_set_fd(pktio_entry->s.pkt_nm.sockfd, pktio_entry->s.pkt_nm.if_name, enable); } static int netmap_promisc_mode_get(pktio_entry_t *pktio_entry) { + if (pktio_entry->s.pkt_nm.is_virtual) + return 0; + return promisc_mode_get_fd(pktio_entry->s.pkt_nm.sockfd, pktio_entry->s.pkt_nm.if_name); } -- 1.9.1 _______________________________________________ lng-odp mailing list [email protected] https://lists.linaro.org/mailman/listinfo/lng-odp
