diff options
Diffstat (limited to 'accel-dp/kni_dev.c')
-rw-r--r-- | accel-dp/kni_dev.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/accel-dp/kni_dev.c b/accel-dp/kni_dev.c new file mode 100644 index 00000000..bafe9767 --- /dev/null +++ b/accel-dp/kni_dev.c @@ -0,0 +1,213 @@ +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <linux/if.h> + +#include <rte_config.h> +#include <rte_mbuf.h> +#include <rte_ethdev.h> +#include <rte_kni.h> +#include <rte_malloc.h> +#include <rte_errno.h> + +#include "init.h" +#include "conf_file.h" +#include "common.h" +#include "dev.h" +#include "kni_dev.h" + +#include "iputils.h" + +struct knidev { + int port; + int xport; + struct net_device *dev; + struct rte_kni *kni; + int ifindex; +}; + +static int kni_cnt; +static struct knidev **dev_list; + +int kni_dev_count() +{ + return kni_cnt; +} + +uint16_t kni_dev_rx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, const uint16_t nb_pkts) +{ + return rte_kni_rx_burst(dev_list[port_id]->kni, rx_pkts, nb_pkts); +} + +uint16_t kni_dev_tx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) +{ + return rte_kni_tx_burst(dev_list[port_id]->kni, tx_pkts, nb_pkts); +} + +static void knidev_xmit(struct rte_mbuf *mbuf, struct net_device *dev) +{ + struct knidev *kni_dev = netdev_priv(dev); + + mbuf->port = kni_dev->xport; +} + +static int kni_change_mtu(uint8_t port, unsigned mtu) +{ + return 0; +} + +static int kni_config_network_if(uint8_t port, uint8_t if_up) +{ + return 0; +} + +static int parse_ip_addr(const char *str, in_addr_t *addr, int *mask) +{ + char *ptr = strchr(str, '/'); + char tmp[32]; + + if (ptr) { + memcpy(tmp, str, ptr - str); + tmp[ptr - str] = 0; + *addr = inet_addr(tmp); + *mask = atoi(ptr + 1); + if (*mask <= 0 || *mask > 32) + return -1; + } else { + *addr = inet_addr(str); + *mask = 32; + } + + return *addr == INADDR_NONE; +} + +struct ifconfig_arg { + struct knidev *dev; + struct conf_opt *opt; + int err; +}; + +static void *kni_ifconfig(void *a) +{ + struct ifconfig_arg *arg = a; + struct knidev *dev = arg->dev; + struct conf_opt *opt = arg->opt; + struct ifreq ifr; + const char *opt1; + in_addr_t addr; + int mask; + + strcpy(ifr.ifr_name, opt->name); + + if (ioctl(sock_fd, SIOCGIFINDEX, &ifr, sizeof(ifr))) { + fprintf(stderr, "%s: SIOCGIFINDEX: %s\n", opt->name, strerror(errno)); + arg->err = errno; + return NULL; + } + + dev->ifindex = ifr.ifr_ifindex; + + ioctl(sock_fd, SIOCGIFFLAGS, &ifr, sizeof(ifr)); + + ifr.ifr_flags |= IFF_UP | IFF_NOARP; + + while (ioctl(sock_fd, SIOCSIFFLAGS, &ifr, sizeof(ifr))) + sleep(1); + + opt1 = conf_get_subopt(opt, "ip-addr"); + if (opt1) { + if (parse_ip_addr(opt1, &addr, &mask)) { + arg->err = EINVAL; + return NULL; + } + + ipaddr_add(dev->ifindex, addr, mask); + } + + arg->err = 0; + + return NULL; +} + +int kni_dev_init(struct rte_mempool *mbuf_pool) +{ + struct conf_sect *s = conf_get_sect("interface"); + struct conf_opt *opt; + struct rte_kni_conf conf; + struct rte_kni_ops ops; + struct rte_kni *kni; + struct net_device *dev; + struct knidev *knidev; + pthread_t tid; + struct ifconfig_arg arg; + int i = 0, x = rte_eth_dev_count(); + + for (opt = s->opt; opt; opt = opt->next) { + const char *busid = conf_get_subopt(opt, "busid"); + if (!strcmp(busid, "kni")) + kni_cnt++; + } + + if (!kni_cnt) + return 0; + + rte_kni_init(kni_cnt); + + dev_list = rte_malloc(NULL, kni_cnt * sizeof(void *), 0); + + memset(&conf, 0, sizeof(conf)); + memset(&ops, 0, sizeof(ops)); + + ops.change_mtu = kni_change_mtu; + ops.config_network_if = kni_config_network_if; + + for (opt = s->opt; opt; opt = opt->next) { + const char *busid = conf_get_subopt(opt, "busid"); + if (strcmp(busid, "kni")) + continue; + + strcpy(conf.name, opt->name); + conf.group_id = i; + conf.mbuf_size = ETHER_MAX_LEN + 8; + + ops.port_id = i; + + kni = rte_kni_alloc(mbuf_pool, &conf, &ops); + + if (!kni) { + fprintf(stderr, "failed to create %s\n", opt->name); + return -1; + } + + dev = netdev_alloc(opt->name, sizeof(*knidev), NULL); + dev->xmit = knidev_xmit; + knidev = netdev_priv(dev); + knidev->port = i; + knidev->xport = i + x; + knidev->dev = dev; + knidev->kni = kni; + + dev_list[i] = knidev; + + arg.dev = knidev; + arg.opt = opt; + arg.err = -1; + + pthread_create(&tid, NULL, kni_ifconfig, &arg); + + while (arg.err == -1) + rte_kni_handle_request(kni); + + pthread_join(tid, NULL); + + if (arg.err != 0) + return -1; + } + + return 0; +} + |