This looks very useful, no more headaches figuring out what system
loopback device to use.

On Thu, Jan 8, 2015 at 6:09 PM, Stuart Haslam <[email protected]> wrote:
> Create a new linux-generic pktio type ODP_PKTIO_TYPE_LOOPBACK which
> will be used when the "loop" device is opened. A queue is used to
> connect the pktio output queue to the input queue. Packets sent to the
> loopback device are classified before making it to the input queue.
> A random MAC address is assigned when the device is opened, and the
> other control functions (MTU/promisc) are just dummies.
>
> As this doesn't need root access, the odp_pktio_run script is modified
> to use the "loop" device when not root. The veth method is still used
> when running as root (on linux-generic) so that the socket code
> actually gets tested.
>
> Signed-off-by: Stuart Haslam <[email protected]>
> ---
> (This code contribution is provided under the terms of agreement 
> LES-LTM-21309)
>
>  .../linux-generic/include/odp_packet_io_internal.h |   3 +
>  platform/linux-generic/odp_packet_io.c             | 116 
> ++++++++++++++++-----
>  test/validation/odp_pktio_run                      |  11 +-
>  3 files changed, 99 insertions(+), 31 deletions(-)
>
> diff --git a/platform/linux-generic/include/odp_packet_io_internal.h 
> b/platform/linux-generic/include/odp_packet_io_internal.h
> index 465127b..ea97a88 100644
> --- a/platform/linux-generic/include/odp_packet_io_internal.h
> +++ b/platform/linux-generic/include/odp_packet_io_internal.h
> @@ -34,6 +34,7 @@ typedef enum {
>         ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
>         ODP_PKTIO_TYPE_SOCKET_MMSG,
>         ODP_PKTIO_TYPE_SOCKET_MMAP,
> +       ODP_PKTIO_TYPE_LOOPBACK,
>  } odp_pktio_type_t;
>
>  struct pktio_entry {
> @@ -41,12 +42,14 @@ struct pktio_entry {
>         int taken;                      /**< is entry taken(1) or free(0) */
>         odp_queue_t inq_default;        /**< default input queue, if set */
>         odp_queue_t outq_default;       /**< default out queue */
> +       odp_queue_t loopq;              /**< loopback queue */
>         odp_pktio_type_t type;          /**< pktio type */
>         pkt_sock_t pkt_sock;            /**< using socket API for IO */
>         pkt_sock_mmap_t pkt_sock_mmap;  /**< using socket mmap API for IO */
>         classifier_t cls;               /**< classifier linked with this 
> pktio*/
>         char name[IFNAMSIZ];            /**< name of pktio provided to
>                                            pktio_open() */
> +       odp_bool_t promisc;             /**< promiscuous mode state */
>  };
>
>  typedef union {
> diff --git a/platform/linux-generic/odp_packet_io.c 
> b/platform/linux-generic/odp_packet_io.c
> index 59590d2..7335dd3 100644
> --- a/platform/linux-generic/odp_packet_io.c
> +++ b/platform/linux-generic/odp_packet_io.c
> @@ -18,11 +18,13 @@
>  #include <odp_schedule_internal.h>
>  #include <odp_classification_internal.h>
>  #include <odp_debug_internal.h>
> +#include <odp_time.h>
>
>  #include <string.h>
>  #include <sys/ioctl.h>
>  #include <linux/if_arp.h>
>  #include <ifaddrs.h>
> +#include <stdlib.h>
>
>  static pktio_table_t *pktio_tbl;
>
> @@ -160,14 +162,28 @@ static int free_pktio_entry(odp_pktio_t id)
>         return 0;
>  }
>
> +static int random_mac(void *mac_addr, size_t addr_size)
> +{
> +       uint32_t ethaddr_l, ethaddr_h;
> +
> +       srand(odp_time_cycles());
> +       ethaddr_h = (rand() & 0xfeff) | 0x0200;
> +       ethaddr_l = rand();
> +
> +       snprintf(mac_addr, addr_size, "%02x:%02x:%02x:%02x:%02x:%02x",
> +                ethaddr_h >> 8, ethaddr_h & 0xff,
> +                ethaddr_l >> 24, (ethaddr_l >> 16) & 0xff,
> +                (ethaddr_l >> 8) & 0xff, ethaddr_l & 0xff);
> +
> +       return 0;
> +}
> +
>  odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool)
>  {
>         odp_pktio_t id;
>         pktio_entry_t *pktio_entry;
>         int res;
>         int fanout = 1;
> -       char loop[IFNAMSIZ] = {0};
> -       char *loop_hint;
>
>         if (strlen(dev) >= IFNAMSIZ) {
>                 /* ioctl names limitation */
> @@ -176,28 +192,6 @@ odp_pktio_t odp_pktio_open(const char *dev, 
> odp_buffer_pool_t pool)
>                 return ODP_PKTIO_INVALID;
>         }
>
> -       if (!strcmp(dev, "loop")) {
> -               /* If hint with ODP_PKTIO_LOOPDEV is provided, use hint,
> -                * if not try to find usable device.
> -                */
> -               loop_hint = getenv("ODP_PKTIO_LOOPDEV");
> -               if (!loop_hint || (strlen(loop_hint) == 0)) {
> -                       ODP_ERR("Set loop with ODP_PKTIO_LOOPDEV=ethX\n");
> -                       return ODP_PKTIO_INVALID;
> -               }
> -
> -               if (strlen(loop_hint) >= IFNAMSIZ) {
> -                       ODP_ERR("pktio name %s is too big, limit is %d 
> bytes\n",
> -                               loop_hint, IFNAMSIZ);
> -                       return ODP_PKTIO_INVALID;
> -               }
> -
> -               memset(loop, 0, IFNAMSIZ);
> -               memcpy(loop, loop_hint, strlen(loop_hint));
> -               dev = loop;
> -               ODP_DBG("pktio using %s as loopback device\n", loop_hint);
> -       }
> -
>         id = alloc_lock_pktio_entry();
>         if (id == ODP_PKTIO_INVALID) {
>                 ODP_ERR("No resources available.\n");
> @@ -209,6 +203,22 @@ odp_pktio_t odp_pktio_open(const char *dev, 
> odp_buffer_pool_t pool)
>         if (!pktio_entry)
>                 return ODP_PKTIO_INVALID;
>
> +       if (strcmp(dev, "loop") == 0) {
> +               char loopq_name[ODP_QUEUE_NAME_LEN];
> +               ODP_DBG("pktio opening loop devive\n");

typo devive

> +
> +               pktio_entry->s.type = ODP_PKTIO_TYPE_LOOPBACK;
> +               snprintf(loopq_name, sizeof(loopq_name), "%i-pktio_loopq",
> +                        (int)id);
> +               pktio_entry->s.loopq = odp_queue_create(loopq_name,
> +                                                       ODP_QUEUE_TYPE_POLL,
> +                                                       NULL);
> +               random_mac(pktio_entry->s.pkt_sock.if_mac,
> +                          sizeof(pktio_entry->s.pkt_sock.if_mac));
> +
> +               goto done;
> +       }
> +
>         ODP_DBG("ODP_PKTIO_USE_FANOUT: %d\n", fanout);
>         if (getenv("ODP_PKTIO_DISABLE_SOCKET_MMAP") == NULL) {
>                 pktio_entry->s.type = ODP_PKTIO_TYPE_SOCKET_MMAP;
> @@ -271,6 +281,10 @@ int odp_pktio_close(odp_pktio_t id)
>                 case ODP_PKTIO_TYPE_SOCKET_MMAP:
>                         res  = close_pkt_sock_mmap(&entry->s.pkt_sock_mmap);
>                         break;
> +               case ODP_PKTIO_TYPE_LOOPBACK:
> +                       /* @todo: destroy loopback queue */
> +                       res = 0;
> +                       break;
>                 default:
>                         break;
>                 }
> @@ -284,6 +298,22 @@ int odp_pktio_close(odp_pktio_t id)
>         return 0;
>  }
>
> +static int deq_loopback(pktio_entry_t *pktio_entry, odp_packet_t pkt_tbl[],
> +                       unsigned len)
> +{
> +       int nbr, i;
> +       odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
> +       queue_entry_t *qentry;
> +
> +       qentry = queue_to_qentry(pktio_entry->s.loopq);
> +       nbr = queue_deq_multi(qentry, hdr_tbl, len);
> +
> +       for (i = 0; i < nbr; ++i)
> +               pkt_tbl[i] = 
> odp_packet_from_buffer(odp_hdr_to_buf(hdr_tbl[i]));
> +
> +       return nbr;
> +}
> +
>  int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
>  {
>         pktio_entry_t *pktio_entry = get_pktio_entry(id);
> @@ -307,6 +337,9 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t 
> pkt_table[], unsigned len)
>                 pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>                                 pkt_table, len);
>                 break;
> +       case ODP_PKTIO_TYPE_LOOPBACK:
> +               pkts = deq_loopback(pktio_entry, pkt_table, len);
> +               break;
>         default:
>                 pkts = -1;
>                 break;
> @@ -322,6 +355,20 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t 
> pkt_table[], unsigned len)
>         return pkts;
>  }
>
> +static int enq_loopback(pktio_entry_t *pktio_entry, odp_packet_t pkt_tbl[],
> +                       unsigned len)
> +{
> +       odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
> +       queue_entry_t *qentry;
> +       unsigned i;
> +
> +       for (i = 0; i < len; ++i)
> +               hdr_tbl[i] = odp_buf_to_hdr(odp_packet_to_buffer(pkt_tbl[i]));
> +
> +       qentry = queue_to_qentry(pktio_entry->s.loopq);
> +       return queue_enq_multi(qentry, hdr_tbl, len) == 0 ? len : 0;
> +}
> +
>  int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
>  {
>         pktio_entry_t *pktio_entry = get_pktio_entry(id);
> @@ -344,6 +391,9 @@ int odp_pktio_send(odp_pktio_t id, odp_packet_t 
> pkt_table[], unsigned len)
>                 pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>                                 pkt_table, len);
>                 break;
> +       case ODP_PKTIO_TYPE_LOOPBACK:
> +               pkts = enq_loopback(pktio_entry, pkt_table, len);
> +               break;
>         default:
>                 pkts = -1;
>         }
> @@ -559,6 +609,11 @@ int odp_pktio_mtu(odp_pktio_t id)
>                 return -1;
>         }
>
> +       if (entry->s.type == ODP_PKTIO_TYPE_LOOPBACK) {
> +               unlock_entry(entry);
> +               return 1500;
> +       }
> +
>         sockfd = sockfd_from_pktio_entry(entry);
>         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", entry->s.name);
>
> @@ -594,6 +649,13 @@ int odp_pktio_promisc_mode_set(odp_pktio_t id, 
> odp_bool_t enable)
>                 return -1;
>         }
>
> +       entry->s.promisc = enable;
> +
> +       if (entry->s.type == ODP_PKTIO_TYPE_LOOPBACK) {
> +               unlock_entry(entry);
> +               return 0;
> +       }
> +
>         sockfd = sockfd_from_pktio_entry(entry);
>         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", entry->s.name);
>
> @@ -641,6 +703,11 @@ int odp_pktio_promisc_mode(odp_pktio_t id)
>                 return -1;
>         }
>
> +       if (entry->s.type == ODP_PKTIO_TYPE_LOOPBACK) {
> +               unlock_entry(entry);
> +               return entry->s.promisc ? 1 : 0;
> +       }
> +
>         sockfd = sockfd_from_pktio_entry(entry);
>         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", entry->s.name);
>
> @@ -683,6 +750,7 @@ size_t odp_pktio_mac_addr(odp_pktio_t id, void *mac_addr,
>         switch (entry->s.type) {
>         case ODP_PKTIO_TYPE_SOCKET_BASIC:
>         case ODP_PKTIO_TYPE_SOCKET_MMSG:
> +       case ODP_PKTIO_TYPE_LOOPBACK:
>                 memcpy(mac_addr, entry->s.pkt_sock.if_mac,
>                        ETH_ALEN);
>                 break;
> diff --git a/test/validation/odp_pktio_run b/test/validation/odp_pktio_run
> index d4d6b2c..08288e6 100755
> --- a/test/validation/odp_pktio_run
> +++ b/test/validation/odp_pktio_run
> @@ -100,11 +100,13 @@ run_test()
>
>  run()
>  {
> -       if [ "$ODP_PLATFORM" != "linux-generic" ]; then
> +       if [ "$ODP_PLATFORM" != "linux-generic" -o "$(id -u)" != "0" ]; then
>                 echo "pktio: using 'loop' device"
>                 $TEST_DIR/odp_pktio
>                 exit $?
> -       elif [ "$ODP_PKTIO_IF0" = "" ]; then
> +       fi
> +
> +       if [ "$ODP_PKTIO_IF0" = "" ]; then
>                 # no interfaces specified on linux-generic, use defaults
>                 setup_env1 clean
>                 export ODP_PKTIO_IF0=$IF0
> @@ -120,11 +122,6 @@ if [ "$ODP_PLATFORM" = "" ]; then
>         exit 1
>  fi
>
> -if [ "$(id -u)" != "0" ]; then
> -       echo "pktio: error: must be run as root"
> -       exit $TEST_SKIPPED
> -fi
> -
>  case "$1" in
>         setup)   setup_env1   ;;
>         cleanup) cleanup_env1 ;;
> --
> 2.1.1
>
>
>
> _______________________________________________
> lng-odp mailing list
> [email protected]
> http://lists.linaro.org/mailman/listinfo/lng-odp

_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to