Date: Sun, 3 Jun 2018 22:26:27 GMT From: sduo@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r337259 - in soc2018/sduo/head: sys/net tools/tools/vale_vlan Message-ID: <201806032226.w53MQRIm076674@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sduo Date: Sun Jun 3 22:26:26 2018 New Revision: 337259 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=337259 Log: Added vale-vlan-ctl, a simple cli tool to manage vlan configurations. Added: soc2018/sduo/head/tools/tools/vale_vlan/ soc2018/sduo/head/tools/tools/vale_vlan/Makefile soc2018/sduo/head/tools/tools/vale_vlan/vale-vlan-ctl.c Modified: soc2018/sduo/head/sys/net/vale_vlan_user.h Modified: soc2018/sduo/head/sys/net/vale_vlan_user.h ============================================================================== --- soc2018/sduo/head/sys/net/vale_vlan_user.h Mon May 28 20:05:50 2018 (r337258) +++ soc2018/sduo/head/sys/net/vale_vlan_user.h Sun Jun 3 22:26:26 2018 (r337259) @@ -36,7 +36,7 @@ -/* struct passed between user and kernel during read and write operations */ +/* struct passed between user and kernel during write operations */ struct vlan_conf_entry { char port_name[IF_NAMESIZE]; #define TRUNK_PORT 0x01 Added: soc2018/sduo/head/tools/tools/vale_vlan/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2018/sduo/head/tools/tools/vale_vlan/Makefile Sun Jun 3 22:26:26 2018 (r337259) @@ -0,0 +1,12 @@ +PROGS=vale-vlan-ctl +CLEANFILES = $(PROGS) *.o +CFLAGS += -Werror -Wall +CFLAGS += -Wextra +SRCS=vale-vlan-ctl.c +MAN= +.include <bsd.prog.mk> + +all: $(PROGS) + +vale-vlan-ctl: vale-vlan-ctl.o + $(CC) $(CFLAGS) vale-vlan-ctl.c -o vale-vlan-ctl \ No newline at end of file Added: soc2018/sduo/head/tools/tools/vale_vlan/vale-vlan-ctl.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2018/sduo/head/tools/tools/vale_vlan/vale-vlan-ctl.c Sun Jun 3 22:26:26 2018 (r337259) @@ -0,0 +1,375 @@ +#include <stdio.h> +#include <inttypes.h> +#include <unistd.h> +#include <getopt.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <net/if.h> +#include <stdlib.h> +#include <errno.h> +#include <stdbool.h> +#include <string.h> +#include <stdint.h> +#include <sys/time.h> + +#include <net/vale_vlan_user.h> + + + +#define DEVICE_NAME "/dev/vale_vlan" + + + +static bool +str_to_uint16(const char *str, uint16_t *res) +{ + intmax_t val; + char *end; + errno = 0; + + val = strtoimax(str, &end, 10); + if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == str || *end != '\0') { + return false; + } + *res = (uint16_t) val; + return true; +} + + + +static int +vlan_ioctl(int fd, const char *conf_name, uint16_t req_type) +{ + struct vlanreq_header hdr; + + memset(&hdr, 0, sizeof(hdr)); + hdr.vr_req_type = req_type; + snprintf(hdr.vr_conf_name, sizeof(hdr.vr_conf_name), "%s", conf_name); + + return ioctl(fd, VALE_VLAN_IOCCTRL, &hdr); +} + + +static ssize_t +vlan_write(int fd, const char *port_name, uint8_t port_type, uint8_t action, + uint16_t vlan_id) +{ + struct vlan_conf_entry entry; + + memset(&entry, 0, sizeof(entry)); + if (port_name) { + snprintf(entry.port_name, sizeof(entry.port_name), + "%s", + port_name); + } + entry.port_type = port_type; + entry.vlan_id = vlan_id; + entry.action = action; + + return write(fd, &entry, sizeof(entry)); +} + + +#define MAX_LIST_ENTRIES 256 + +static void +list_conf(int fd) +{ + struct port *port_entries = NULL; + int ret; + int i; + + port_entries = malloc(sizeof(struct port) * MAX_LIST_ENTRIES); + if (!port_entries) { + exit(EXIT_FAILURE); + } + + ret = read(fd, port_entries, sizeof(struct port) * MAX_LIST_ENTRIES); + if (ret < 0) { + perror(""); + exit(EXIT_FAILURE); + } + for (i = 0; i < ret / (int)sizeof(struct port); ++i) { + printf("%s%s, type:", + port_entries[i].bdg_name, + port_entries[i].port_name); + if (port_entries[i].port_type == TRUNK_PORT) { + printf("trunk port\n"); + } else { + printf("access port, vlan id:%d\n", + port_entries[i].vlan_id); + } + } + + free(port_entries); +} + + + +static int +valid_port_name(const char *conf_name) +{ + + return (strlen(conf_name) + 1) <= IF_NAMESIZE; +} + + + +static void +attach_vlan_port(int fd, char *port_and_vlan, int create) +{ + char port_name[IF_NAMESIZE]; + uint16_t vlan_id = 0; + uint8_t action; + ssize_t ret; + char *token; + + token = strtok(port_and_vlan, "="); + if (!token) { + /* cannot happen (?) */ + fprintf(stderr, "You must specify a vlan id\n"); + exit(EXIT_FAILURE); + } + if (!valid_port_name(token)) { + fprintf(stderr, "Max port name length = %d\n", IF_NAMESIZE); + exit(EXIT_FAILURE); + } + snprintf(port_name, sizeof(port_name), "%s", token); + + token = strtok(NULL, "="); + if (!token) { + fprintf(stderr, "You must specify a vlan id\n"); + exit(EXIT_FAILURE); + } + if (!str_to_uint16(token, &vlan_id) || vlan_id > 4095) { + fprintf(stderr, "Invalid vlan id: %u\n", vlan_id); + exit(EXIT_FAILURE); + } + + action = create ? CREATE_AND_ATTACH_PORT : ATTACH_PORT; + ret = vlan_write(fd, port_name, VLAN_PORT, action, vlan_id); + if (ret < 0) { + perror(port_name); + exit(EXIT_FAILURE); + } +} + + + +static void +detach_vlan_port(int fd, const char *port_name, int destroy) +{ + uint8_t action; + ssize_t ret; + + action = destroy ? DETACH_AND_DESTROY_PORT : DETACH_PORT; + ret = vlan_write(fd, port_name, VLAN_PORT, action, 0xFFF); + if (ret < 0) { + perror(port_name); + exit(EXIT_FAILURE); + } +} + + + +static void +attach_trunk_port(int fd, const char *port_name, int create) +{ + uint8_t action; + ssize_t ret; + + if (!valid_port_name(port_name)) { + fprintf(stderr, "Max port name length = %d\n", IF_NAMESIZE); + exit(EXIT_FAILURE); + } + + action = create ? CREATE_AND_ATTACH_PORT : ATTACH_PORT; + ret = vlan_write(fd, port_name, TRUNK_PORT, action, 0xFFF); + if (ret < 0) { + perror(port_name); + exit(EXIT_FAILURE); + } +} + + + +static void +detach_trunk_port(int fd, int destroy) +{ + uint8_t action; + ssize_t ret; + + action = destroy ? DETACH_AND_DESTROY_PORT : DETACH_PORT; + ret = vlan_write(fd, NULL, TRUNK_PORT, action, 0xFFF); + if (ret < 0) { + perror(""); + exit(EXIT_FAILURE); + } +} + + + +static int +valid_conf_name(const char *conf_name) +{ + + return (strlen(conf_name) + 1) <= CONF_NAME_LENGTH; +} + + + +static void +create_conf(int fd, const char *conf_name) +{ + int ret; + + if (!valid_conf_name(conf_name)) { + fprintf(stderr, "Max conf name length = %d\n", + CONF_NAME_LENGTH - 1); + exit(EXIT_FAILURE); + } + + ret = vlan_ioctl(fd, conf_name, VLAN_REQ_CREATE_CONF); + if (ret < 0) { + perror(conf_name); + exit(EXIT_FAILURE); + } +} + + + +static void +delete_conf(int fd, const char *conf_name) +{ + int ret; + + if (!valid_conf_name(conf_name)) { + fprintf(stderr, "Max conf name length = %d\n", + CONF_NAME_LENGTH - 1); + exit(EXIT_FAILURE); + } + + ret = vlan_ioctl(fd, conf_name, VLAN_REQ_DELETE_CONF); + if (ret < 0) { + perror(conf_name); + exit(EXIT_FAILURE); + } +} + + + +static void +select_conf(int fd, const char *conf_name) +{ + int ret; + + if (!valid_conf_name(conf_name)) { + fprintf(stderr, "Max conf name length = %d\n", + CONF_NAME_LENGTH - 1); + exit(EXIT_FAILURE); + } + + ret = vlan_ioctl(fd, conf_name, VLAN_REQ_SELECT_CONF); + if (ret < 0) { + perror(conf_name); + exit(EXIT_FAILURE); + } +} + + + +static void +usage(const char *file_name, FILE *std_stream) +{ + + fprintf(std_stream, + "Usage:\n" + "%s arguments\n" + "\t-n conf_name create (and select) configuration " + "conf_name\n" + "\t-r conf_name delete configuration conf_name\n" + "\t-s conf_name select configuration conf_name\n" + "\t-t interface attach interface as trunk port\n" + "\t-T detach trunk port\n" + "\t-p interfaces create persistent VALE port " + "and attach it as trunk port\n" + "\t-P detach trunk port and destroy it (must " + "have been created through -p)\n" + "\t-a interface=vlan_id attach interface as vlan port with id " + "vlan_id\n" + "\t-A interface detach vlan port interface\n" + "\t-c interface=vlan_id create persistent VALE port and attach " + "it as vlan port with id vlan_id\n" + "\t-C interface detach vlan port interface and destroy " + "it (must have been created through -c)\n" + "\t-l list attached interfaces\n", + file_name); + exit(EXIT_FAILURE); +} + + + +int +main(int argc, char **argv) +{ + int fd; + char c; + + if (argc == 1) { + usage(argv[0], stderr); + } + + fd = open(DEVICE_NAME, O_RDWR); + if (fd < 0) { + perror(DEVICE_NAME); + exit(EXIT_FAILURE); + } + + while ((c = getopt(argc, argv, "n:s:r:t:Tp:Pc:C:a:A:hl")) != -1) { + switch (c) { + case 't': /* attach trunk port */ + attach_trunk_port(fd, optarg, 0 /* don't create */); + break; + case 'T': /* detach trunk port */ + detach_trunk_port(fd, 0 /* don't destroy */); + break; + case 'p': /* create and attach trunk port */ + attach_trunk_port(fd, optarg, 1 /* create */); + break; + case 'P': /* detach and destroy trunk port */ + detach_trunk_port(fd, 1 /* destroy */); + break; + case 'a': /* attach vlan port */ + attach_vlan_port(fd, optarg, 0 /* don't create */); + break; + case 'A': /* detach vlan port */ + detach_vlan_port(fd, optarg, 0 /* don't destroy */); + break; + case 'c': /* create and attach vlan port */ + attach_vlan_port(fd, optarg, 1 /* create */); + break; + case 'C': /* detach and destroy vlan port */ + detach_vlan_port(fd, optarg, 1 /* destroy */); + break; + case 'n': /* create new configuration */ + create_conf(fd, optarg); + break; + case 'r': /* destroy existing configuration */ + delete_conf(fd, optarg); + break; + case 's': /* select existing configuration */ + select_conf(fd, optarg); + break; + case 'l': /* list existing configuration */ + list_conf(fd); + break; + case 'h': /* help */ + default: /* error, unknown option or missing parameter */ + usage(argv[0], stdout); + exit(EXIT_FAILURE); + } + } + return 0; +} \ No newline at end of file
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806032226.w53MQRIm076674>