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

Reply via email to