1235289Sadrian/*- 2235289Sadrian * Copyright (c) 2011-2012 Stefan Bethke. 3235289Sadrian * All rights reserved. 4235289Sadrian * 5235289Sadrian * Redistribution and use in source and binary forms, with or without 6235289Sadrian * modification, are permitted provided that the following conditions 7235289Sadrian * are met: 8235289Sadrian * 1. Redistributions of source code must retain the above copyright 9235289Sadrian * notice, this list of conditions and the following disclaimer. 10235289Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11235289Sadrian * notice, this list of conditions and the following disclaimer in the 12235289Sadrian * documentation and/or other materials provided with the distribution. 13235289Sadrian * 14235289Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15235289Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16235289Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17235289Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18235289Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19235289Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20235289Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21235289Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22235289Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23235289Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24235289Sadrian * SUCH DAMAGE. 25235289Sadrian * 26235289Sadrian * $FreeBSD$ 27235289Sadrian */ 28235289Sadrian 29235289Sadrian#include <sys/cdefs.h> 30235289Sadrian__FBSDID("$FreeBSD$"); 31235289Sadrian 32235289Sadrian#include <ctype.h> 33235289Sadrian#include <err.h> 34235289Sadrian#include <errno.h> 35235289Sadrian#include <fcntl.h> 36235289Sadrian#include <stdio.h> 37235289Sadrian#include <stdlib.h> 38235289Sadrian#include <string.h> 39235289Sadrian#include <sysexits.h> 40235289Sadrian#include <unistd.h> 41235289Sadrian#include <sys/types.h> 42235289Sadrian#include <sys/ioctl.h> 43235289Sadrian#include <net/if.h> 44235289Sadrian#include <net/if_media.h> 45235289Sadrian#include <dev/etherswitch/etherswitch.h> 46235289Sadrian 47235289Sadrianint get_media_subtype(int, const char *); 48235289Sadrianint get_media_mode(int, const char *); 49235289Sadrianint get_media_options(int, const char *); 50235289Sadrianint lookup_media_word(struct ifmedia_description *, const char *); 51235289Sadrianvoid print_media_word(int, int); 52235289Sadrianvoid print_media_word_ifconfig(int); 53235289Sadrian 54235289Sadrian/* some constants */ 55235289Sadrian#define IEEE802DOT1Q_VID_MAX 4094 56235289Sadrian#define IFMEDIAREQ_NULISTENTRIES 256 57235289Sadrian 58235289Sadrianenum cmdmode { 59235289Sadrian MODE_NONE = 0, 60235289Sadrian MODE_PORT, 61250382Sadrian MODE_CONFIG, 62235289Sadrian MODE_VLANGROUP, 63235289Sadrian MODE_REGISTER, 64235289Sadrian MODE_PHYREG 65235289Sadrian}; 66235289Sadrian 67235289Sadrianstruct cfg { 68235289Sadrian int fd; 69235289Sadrian int verbose; 70235289Sadrian int mediatypes; 71235289Sadrian const char *controlfile; 72250382Sadrian etherswitch_conf_t conf; 73235289Sadrian etherswitch_info_t info; 74235289Sadrian enum cmdmode mode; 75235289Sadrian int unit; 76235289Sadrian}; 77235289Sadrian 78235289Sadrianstruct cmds { 79235289Sadrian enum cmdmode mode; 80235289Sadrian const char *name; 81235289Sadrian int args; 82235289Sadrian void (*f)(struct cfg *, char *argv[]); 83235289Sadrian}; 84241720Sedstatic struct cmds cmds[]; 85235289Sadrian 86235289Sadrian 87250382Sadrian/* 88250382Sadrian * Print a value a la the %b format of the kernel's printf. 89250382Sadrian * Stolen from ifconfig.c. 90250382Sadrian */ 91250382Sadrianstatic void 92250382Sadrianprintb(const char *s, unsigned v, const char *bits) 93250382Sadrian{ 94250382Sadrian int i, any = 0; 95250382Sadrian char c; 96235289Sadrian 97250382Sadrian if (bits && *bits == 8) 98250382Sadrian printf("%s=%o", s, v); 99250382Sadrian else 100250382Sadrian printf("%s=%x", s, v); 101250382Sadrian bits++; 102250382Sadrian if (bits) { 103250382Sadrian putchar('<'); 104250382Sadrian while ((i = *bits++) != '\0') { 105250382Sadrian if (v & (1 << (i-1))) { 106250382Sadrian if (any) 107250382Sadrian putchar(','); 108250382Sadrian any = 1; 109250382Sadrian for (; (c = *bits) > 32; bits++) 110250382Sadrian putchar(c); 111250382Sadrian } else 112250382Sadrian for (; *bits > 32; bits++) 113250382Sadrian ; 114250382Sadrian } 115250382Sadrian putchar('>'); 116250382Sadrian } 117250382Sadrian} 118250382Sadrian 119235289Sadrianstatic int 120235289Sadrianread_register(struct cfg *cfg, int r) 121235289Sadrian{ 122235289Sadrian struct etherswitch_reg er; 123235289Sadrian 124235289Sadrian er.reg = r; 125235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETREG, &er) != 0) 126235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETREG)"); 127235289Sadrian return (er.val); 128235289Sadrian} 129235289Sadrian 130235289Sadrianstatic void 131235289Sadrianwrite_register(struct cfg *cfg, int r, int v) 132235289Sadrian{ 133235289Sadrian struct etherswitch_reg er; 134235289Sadrian 135235289Sadrian er.reg = r; 136235289Sadrian er.val = v; 137235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETREG, &er) != 0) 138235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETREG)"); 139235289Sadrian} 140235289Sadrian 141235289Sadrianstatic int 142235289Sadrianread_phyregister(struct cfg *cfg, int phy, int reg) 143235289Sadrian{ 144235289Sadrian struct etherswitch_phyreg er; 145235289Sadrian 146235289Sadrian er.phy = phy; 147235289Sadrian er.reg = reg; 148235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETPHYREG, &er) != 0) 149235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETPHYREG)"); 150235289Sadrian return (er.val); 151235289Sadrian} 152235289Sadrian 153235289Sadrianstatic void 154235289Sadrianwrite_phyregister(struct cfg *cfg, int phy, int reg, int val) 155235289Sadrian{ 156235289Sadrian struct etherswitch_phyreg er; 157235289Sadrian 158235289Sadrian er.phy = phy; 159235289Sadrian er.reg = reg; 160235289Sadrian er.val = val; 161235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETPHYREG, &er) != 0) 162235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETPHYREG)"); 163235289Sadrian} 164235289Sadrian 165235289Sadrianstatic void 166249752Sadrianset_port_vid(struct cfg *cfg, char *argv[]) 167235289Sadrian{ 168235289Sadrian int v; 169235289Sadrian etherswitch_port_t p; 170235289Sadrian 171235289Sadrian v = strtol(argv[1], NULL, 0); 172249752Sadrian if (v < 0 || v > IEEE802DOT1Q_VID_MAX) 173249752Sadrian errx(EX_USAGE, "pvid must be between 0 and %d", 174249752Sadrian IEEE802DOT1Q_VID_MAX); 175249747Sadrian bzero(&p, sizeof(p)); 176235289Sadrian p.es_port = cfg->unit; 177235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) 178235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); 179249752Sadrian p.es_pvid = v; 180235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0) 181235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)"); 182235289Sadrian} 183235289Sadrian 184235289Sadrianstatic void 185250382Sadrianset_port_flag(struct cfg *cfg, char *argv[]) 186250382Sadrian{ 187250382Sadrian char *flag; 188250382Sadrian int n; 189250382Sadrian uint32_t f; 190250382Sadrian etherswitch_port_t p; 191250382Sadrian 192250382Sadrian n = 0; 193250382Sadrian f = 0; 194250382Sadrian flag = argv[0]; 195250382Sadrian if (strcmp(flag, "none") != 0) { 196250382Sadrian if (*flag == '-') { 197250382Sadrian n++; 198250382Sadrian flag++; 199250382Sadrian } 200250382Sadrian if (strcasecmp(flag, "striptag") == 0) 201250382Sadrian f = ETHERSWITCH_PORT_STRIPTAG; 202250382Sadrian else if (strcasecmp(flag, "addtag") == 0) 203250382Sadrian f = ETHERSWITCH_PORT_ADDTAG; 204250382Sadrian else if (strcasecmp(flag, "firstlock") == 0) 205250382Sadrian f = ETHERSWITCH_PORT_FIRSTLOCK; 206250382Sadrian else if (strcasecmp(flag, "dropuntagged") == 0) 207250382Sadrian f = ETHERSWITCH_PORT_DROPUNTAGGED; 208250382Sadrian else if (strcasecmp(flag, "doubletag") == 0) 209250382Sadrian f = ETHERSWITCH_PORT_DOUBLE_TAG; 210250382Sadrian else if (strcasecmp(flag, "ingress") == 0) 211250382Sadrian f = ETHERSWITCH_PORT_INGRESS; 212250382Sadrian } 213250382Sadrian bzero(&p, sizeof(p)); 214250382Sadrian p.es_port = cfg->unit; 215250382Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) 216250382Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); 217250382Sadrian if (n) 218250382Sadrian p.es_flags &= ~f; 219250382Sadrian else 220250382Sadrian p.es_flags |= f; 221250382Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0) 222250382Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)"); 223250382Sadrian} 224250382Sadrian 225250382Sadrianstatic void 226235289Sadrianset_port_media(struct cfg *cfg, char *argv[]) 227235289Sadrian{ 228235289Sadrian etherswitch_port_t p; 229235289Sadrian int ifm_ulist[IFMEDIAREQ_NULISTENTRIES]; 230235289Sadrian int subtype; 231235289Sadrian 232235289Sadrian bzero(&p, sizeof(p)); 233235289Sadrian p.es_port = cfg->unit; 234235289Sadrian p.es_ifmr.ifm_ulist = ifm_ulist; 235235289Sadrian p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES; 236235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) 237235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); 238235289Sadrian subtype = get_media_subtype(IFM_TYPE(ifm_ulist[0]), argv[1]); 239235289Sadrian p.es_ifr.ifr_media = (p.es_ifmr.ifm_current & IFM_IMASK) | 240235289Sadrian IFM_TYPE(ifm_ulist[0]) | subtype; 241235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0) 242235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)"); 243235289Sadrian} 244235289Sadrian 245235289Sadrianstatic void 246235289Sadrianset_port_mediaopt(struct cfg *cfg, char *argv[]) 247235289Sadrian{ 248235289Sadrian etherswitch_port_t p; 249235289Sadrian int ifm_ulist[IFMEDIAREQ_NULISTENTRIES]; 250235289Sadrian int options; 251235289Sadrian 252235289Sadrian bzero(&p, sizeof(p)); 253235289Sadrian p.es_port = cfg->unit; 254235289Sadrian p.es_ifmr.ifm_ulist = ifm_ulist; 255235289Sadrian p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES; 256235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) 257235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); 258235289Sadrian options = get_media_options(IFM_TYPE(ifm_ulist[0]), argv[1]); 259235289Sadrian if (options == -1) 260235289Sadrian errx(EX_USAGE, "invalid media options \"%s\"", argv[1]); 261235289Sadrian if (options & IFM_HDX) { 262235289Sadrian p.es_ifr.ifr_media &= ~IFM_FDX; 263235289Sadrian options &= ~IFM_HDX; 264235289Sadrian } 265235289Sadrian p.es_ifr.ifr_media |= options; 266235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0) 267235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)"); 268235289Sadrian} 269235289Sadrian 270235289Sadrianstatic void 271235289Sadrianset_vlangroup_vid(struct cfg *cfg, char *argv[]) 272235289Sadrian{ 273235289Sadrian int v; 274235289Sadrian etherswitch_vlangroup_t vg; 275235289Sadrian 276235289Sadrian v = strtol(argv[1], NULL, 0); 277255730Shiren if (v < 0 || v > IEEE802DOT1Q_VID_MAX) 278235289Sadrian errx(EX_USAGE, "vlan must be between 0 and %d", IEEE802DOT1Q_VID_MAX); 279235289Sadrian vg.es_vlangroup = cfg->unit; 280235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0) 281235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)"); 282235289Sadrian vg.es_vid = v; 283235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETVLANGROUP, &vg) != 0) 284235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETVLANGROUP)"); 285235289Sadrian} 286235289Sadrian 287235289Sadrianstatic void 288235289Sadrianset_vlangroup_members(struct cfg *cfg, char *argv[]) 289235289Sadrian{ 290235289Sadrian etherswitch_vlangroup_t vg; 291235289Sadrian int member, untagged; 292235289Sadrian char *c, *d; 293235289Sadrian int v; 294235289Sadrian 295235289Sadrian member = untagged = 0; 296235289Sadrian if (strcmp(argv[1], "none") != 0) { 297235289Sadrian for (c=argv[1]; *c; c=d) { 298235289Sadrian v = strtol(c, &d, 0); 299235289Sadrian if (d == c) 300235289Sadrian break; 301235289Sadrian if (v < 0 || v >= cfg->info.es_nports) 302235289Sadrian errx(EX_USAGE, "Member port must be between 0 and %d", cfg->info.es_nports-1); 303235289Sadrian if (d[0] == ',' || d[0] == '\0' || 304235289Sadrian ((d[0] == 't' || d[0] == 'T') && (d[1] == ',' || d[1] == '\0'))) { 305235289Sadrian if (d[0] == 't' || d[0] == 'T') { 306235289Sadrian untagged &= ~ETHERSWITCH_PORTMASK(v); 307235289Sadrian d++; 308235289Sadrian } else 309235289Sadrian untagged |= ETHERSWITCH_PORTMASK(v); 310235289Sadrian member |= ETHERSWITCH_PORTMASK(v); 311235289Sadrian d++; 312235289Sadrian } else 313235289Sadrian errx(EX_USAGE, "Invalid members specification \"%s\"", d); 314235289Sadrian } 315235289Sadrian } 316235289Sadrian vg.es_vlangroup = cfg->unit; 317235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0) 318235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)"); 319235289Sadrian vg.es_member_ports = member; 320235289Sadrian vg.es_untagged_ports = untagged; 321235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETVLANGROUP, &vg) != 0) 322235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETVLANGROUP)"); 323235289Sadrian} 324235289Sadrian 325235289Sadrianstatic int 326235289Sadrianset_register(struct cfg *cfg, char *arg) 327235289Sadrian{ 328235289Sadrian int a, v; 329235289Sadrian char *c; 330235289Sadrian 331235289Sadrian a = strtol(arg, &c, 0); 332235289Sadrian if (c==arg) 333235289Sadrian return (1); 334235289Sadrian if (*c == '=') { 335235289Sadrian v = strtol(c+1, NULL, 0); 336235289Sadrian write_register(cfg, a, v); 337235289Sadrian } 338235289Sadrian printf("\treg 0x%04x=0x%04x\n", a, read_register(cfg, a)); 339235289Sadrian return (0); 340235289Sadrian} 341235289Sadrian 342235289Sadrianstatic int 343235289Sadrianset_phyregister(struct cfg *cfg, char *arg) 344235289Sadrian{ 345235289Sadrian int phy, reg, val; 346235289Sadrian char *c, *d; 347235289Sadrian 348235289Sadrian phy = strtol(arg, &c, 0); 349235289Sadrian if (c==arg) 350235289Sadrian return (1); 351235289Sadrian if (*c != '.') 352235289Sadrian return (1); 353235289Sadrian d = c+1; 354235289Sadrian reg = strtol(d, &c, 0); 355235289Sadrian if (d == c) 356235289Sadrian return (1); 357235289Sadrian if (*c == '=') { 358235289Sadrian val = strtol(c+1, NULL, 0); 359235289Sadrian write_phyregister(cfg, phy, reg, val); 360235289Sadrian } 361235289Sadrian printf("\treg %d.0x%02x=0x%04x\n", phy, reg, read_phyregister(cfg, phy, reg)); 362235289Sadrian return (0); 363235289Sadrian} 364235289Sadrian 365235289Sadrianstatic void 366250382Sadrianset_vlan_mode(struct cfg *cfg, char *argv[]) 367250382Sadrian{ 368250382Sadrian etherswitch_conf_t conf; 369250382Sadrian 370250382Sadrian bzero(&conf, sizeof(conf)); 371250382Sadrian conf.cmd = ETHERSWITCH_CONF_VLAN_MODE; 372250382Sadrian if (strcasecmp(argv[1], "isl") == 0) 373250382Sadrian conf.vlan_mode = ETHERSWITCH_VLAN_ISL; 374250382Sadrian else if (strcasecmp(argv[1], "port") == 0) 375250382Sadrian conf.vlan_mode = ETHERSWITCH_VLAN_PORT; 376250382Sadrian else if (strcasecmp(argv[1], "dot1q") == 0) 377250382Sadrian conf.vlan_mode = ETHERSWITCH_VLAN_DOT1Q; 378250382Sadrian else if (strcasecmp(argv[1], "dot1q4k") == 0) 379250382Sadrian conf.vlan_mode = ETHERSWITCH_VLAN_DOT1Q_4K; 380250382Sadrian else if (strcasecmp(argv[1], "qinq") == 0) 381250382Sadrian conf.vlan_mode = ETHERSWITCH_VLAN_DOUBLE_TAG; 382250382Sadrian else 383250382Sadrian conf.vlan_mode = 0; 384250382Sadrian if (ioctl(cfg->fd, IOETHERSWITCHSETCONF, &conf) != 0) 385250382Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHSETCONF)"); 386250382Sadrian} 387250382Sadrian 388250382Sadrianstatic void 389250382Sadrianprint_config(struct cfg *cfg) 390250382Sadrian{ 391250382Sadrian const char *c; 392250382Sadrian 393250382Sadrian /* Get the device name. */ 394250382Sadrian c = strrchr(cfg->controlfile, '/'); 395250382Sadrian if (c != NULL) 396250382Sadrian c = c + 1; 397250382Sadrian else 398250382Sadrian c = cfg->controlfile; 399250382Sadrian 400250382Sadrian /* Print VLAN mode. */ 401250382Sadrian if (cfg->conf.cmd & ETHERSWITCH_CONF_VLAN_MODE) { 402250382Sadrian printf("%s: VLAN mode: ", c); 403250382Sadrian switch (cfg->conf.vlan_mode) { 404250382Sadrian case ETHERSWITCH_VLAN_ISL: 405250382Sadrian printf("ISL\n"); 406250382Sadrian break; 407250382Sadrian case ETHERSWITCH_VLAN_PORT: 408250382Sadrian printf("PORT\n"); 409250382Sadrian break; 410250382Sadrian case ETHERSWITCH_VLAN_DOT1Q: 411250382Sadrian printf("DOT1Q\n"); 412250382Sadrian break; 413250382Sadrian case ETHERSWITCH_VLAN_DOT1Q_4K: 414250382Sadrian printf("DOT1Q4K\n"); 415250382Sadrian break; 416250382Sadrian case ETHERSWITCH_VLAN_DOUBLE_TAG: 417250382Sadrian printf("QinQ\n"); 418250382Sadrian break; 419250382Sadrian default: 420250382Sadrian printf("none\n"); 421250382Sadrian } 422250382Sadrian } 423250382Sadrian} 424250382Sadrian 425250382Sadrianstatic void 426235289Sadrianprint_port(struct cfg *cfg, int port) 427235289Sadrian{ 428235289Sadrian etherswitch_port_t p; 429235289Sadrian int ifm_ulist[IFMEDIAREQ_NULISTENTRIES]; 430235289Sadrian int i; 431235289Sadrian 432235289Sadrian bzero(&p, sizeof(p)); 433235289Sadrian p.es_port = port; 434235289Sadrian p.es_ifmr.ifm_ulist = ifm_ulist; 435235289Sadrian p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES; 436235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) 437235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); 438235289Sadrian printf("port%d:\n", port); 439250382Sadrian if (cfg->conf.vlan_mode == ETHERSWITCH_VLAN_DOT1Q) 440250382Sadrian printf("\tpvid: %d\n", p.es_pvid); 441250382Sadrian printb("\tflags", p.es_flags, ETHERSWITCH_PORT_FLAGS_BITS); 442250382Sadrian printf("\n"); 443235289Sadrian printf("\tmedia: "); 444235289Sadrian print_media_word(p.es_ifmr.ifm_current, 1); 445235289Sadrian if (p.es_ifmr.ifm_active != p.es_ifmr.ifm_current) { 446235289Sadrian putchar(' '); 447235289Sadrian putchar('('); 448235289Sadrian print_media_word(p.es_ifmr.ifm_active, 0); 449235289Sadrian putchar(')'); 450235289Sadrian } 451235289Sadrian putchar('\n'); 452235289Sadrian printf("\tstatus: %s\n", (p.es_ifmr.ifm_status & IFM_ACTIVE) != 0 ? "active" : "no carrier"); 453235289Sadrian if (cfg->mediatypes) { 454235289Sadrian printf("\tsupported media:\n"); 455235289Sadrian if (p.es_ifmr.ifm_count > IFMEDIAREQ_NULISTENTRIES) 456235289Sadrian p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES; 457235289Sadrian for (i=0; i<p.es_ifmr.ifm_count; i++) { 458235289Sadrian printf("\t\tmedia "); 459235289Sadrian print_media_word(ifm_ulist[i], 0); 460235289Sadrian putchar('\n'); 461235289Sadrian } 462235289Sadrian } 463235289Sadrian} 464235289Sadrian 465235289Sadrianstatic void 466235289Sadrianprint_vlangroup(struct cfg *cfg, int vlangroup) 467235289Sadrian{ 468235289Sadrian etherswitch_vlangroup_t vg; 469235289Sadrian int i, comma; 470235289Sadrian 471235289Sadrian vg.es_vlangroup = vlangroup; 472235289Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0) 473235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)"); 474253569Sloos if ((vg.es_vid & ETHERSWITCH_VID_VALID) == 0) 475235289Sadrian return; 476253569Sloos vg.es_vid &= ETHERSWITCH_VID_MASK; 477235289Sadrian printf("vlangroup%d:\n", vlangroup); 478250382Sadrian if (cfg->conf.vlan_mode == ETHERSWITCH_VLAN_PORT) 479250382Sadrian printf("\tport: %d\n", vg.es_vid); 480250382Sadrian else 481250382Sadrian printf("\tvlan: %d\n", vg.es_vid); 482235289Sadrian printf("\tmembers "); 483235289Sadrian comma = 0; 484235289Sadrian if (vg.es_member_ports != 0) 485235289Sadrian for (i=0; i<cfg->info.es_nports; i++) { 486235289Sadrian if ((vg.es_member_ports & ETHERSWITCH_PORTMASK(i)) != 0) { 487235289Sadrian if (comma) 488235289Sadrian printf(","); 489235289Sadrian printf("%d", i); 490235289Sadrian if ((vg.es_untagged_ports & ETHERSWITCH_PORTMASK(i)) == 0) 491235289Sadrian printf("t"); 492235289Sadrian comma = 1; 493235289Sadrian } 494235289Sadrian } 495235289Sadrian else 496235289Sadrian printf("none"); 497235289Sadrian printf("\n"); 498235289Sadrian} 499235289Sadrian 500235289Sadrianstatic void 501235289Sadrianprint_info(struct cfg *cfg) 502235289Sadrian{ 503235289Sadrian const char *c; 504235289Sadrian int i; 505235289Sadrian 506235289Sadrian c = strrchr(cfg->controlfile, '/'); 507235289Sadrian if (c != NULL) 508235289Sadrian c = c + 1; 509235289Sadrian else 510235289Sadrian c = cfg->controlfile; 511250382Sadrian if (cfg->verbose) { 512250382Sadrian printf("%s: %s with %d ports and %d VLAN groups\n", c, 513250382Sadrian cfg->info.es_name, cfg->info.es_nports, 514250382Sadrian cfg->info.es_nvlangroups); 515250382Sadrian printf("%s: ", c); 516250382Sadrian printb("VLAN capabilities", cfg->info.es_vlan_caps, 517250382Sadrian ETHERSWITCH_VLAN_CAPS_BITS); 518250382Sadrian printf("\n"); 519250382Sadrian } 520250382Sadrian print_config(cfg); 521235289Sadrian for (i=0; i<cfg->info.es_nports; i++) { 522235289Sadrian print_port(cfg, i); 523235289Sadrian } 524235289Sadrian for (i=0; i<cfg->info.es_nvlangroups; i++) { 525235289Sadrian print_vlangroup(cfg, i); 526235289Sadrian } 527235289Sadrian} 528235289Sadrian 529235289Sadrianstatic void 530250382Sadrianusage(struct cfg *cfg __unused, char *argv[] __unused) 531235289Sadrian{ 532235289Sadrian fprintf(stderr, "usage: etherswitchctl\n"); 533250382Sadrian fprintf(stderr, "\tetherswitchcfg [-f control file] info\n"); 534250382Sadrian fprintf(stderr, "\tetherswitchcfg [-f control file] config " 535250382Sadrian "command parameter\n"); 536250382Sadrian fprintf(stderr, "\t\tconfig commands: vlan_mode\n"); 537250382Sadrian fprintf(stderr, "\tetherswitchcfg [-f control file] phy " 538250382Sadrian "phy.register[=value]\n"); 539250382Sadrian fprintf(stderr, "\tetherswitchcfg [-f control file] portX " 540250382Sadrian "[flags] command parameter\n"); 541250382Sadrian fprintf(stderr, "\t\tport commands: pvid, media, mediaopt\n"); 542250382Sadrian fprintf(stderr, "\tetherswitchcfg [-f control file] reg " 543250382Sadrian "register[=value]\n"); 544250382Sadrian fprintf(stderr, "\tetherswitchcfg [-f control file] vlangroupX " 545250382Sadrian "command parameter\n"); 546250382Sadrian fprintf(stderr, "\t\tvlangroup commands: vlan, members\n"); 547235289Sadrian exit(EX_USAGE); 548235289Sadrian} 549235289Sadrian 550235289Sadrianstatic void 551235289Sadriannewmode(struct cfg *cfg, enum cmdmode mode) 552235289Sadrian{ 553235289Sadrian if (mode == cfg->mode) 554235289Sadrian return; 555235289Sadrian switch (cfg->mode) { 556235289Sadrian case MODE_NONE: 557235289Sadrian break; 558250382Sadrian case MODE_CONFIG: 559250382Sadrian /* 560250382Sadrian * Read the updated the configuration (it can be different 561250382Sadrian * from the last time we read it). 562250382Sadrian */ 563250382Sadrian if (ioctl(cfg->fd, IOETHERSWITCHGETCONF, &cfg->conf) != 0) 564250382Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETCONF)"); 565250382Sadrian print_config(cfg); 566250382Sadrian break; 567235289Sadrian case MODE_PORT: 568235289Sadrian print_port(cfg, cfg->unit); 569235289Sadrian break; 570235289Sadrian case MODE_VLANGROUP: 571235289Sadrian print_vlangroup(cfg, cfg->unit); 572235289Sadrian break; 573235289Sadrian case MODE_REGISTER: 574235289Sadrian case MODE_PHYREG: 575235289Sadrian break; 576235289Sadrian } 577235289Sadrian cfg->mode = mode; 578235289Sadrian} 579235289Sadrian 580235289Sadrianint 581235289Sadrianmain(int argc, char *argv[]) 582235289Sadrian{ 583235289Sadrian int ch; 584235289Sadrian struct cfg cfg; 585235289Sadrian int i; 586235289Sadrian 587235289Sadrian bzero(&cfg, sizeof(cfg)); 588235289Sadrian cfg.controlfile = "/dev/etherswitch0"; 589235289Sadrian while ((ch = getopt(argc, argv, "f:mv?")) != -1) 590235289Sadrian switch(ch) { 591235289Sadrian case 'f': 592235289Sadrian cfg.controlfile = optarg; 593235289Sadrian break; 594235289Sadrian case 'm': 595235289Sadrian cfg.mediatypes++; 596235289Sadrian break; 597235289Sadrian case 'v': 598235289Sadrian cfg.verbose++; 599235289Sadrian break; 600235289Sadrian case '?': 601235289Sadrian /* FALLTHROUGH */ 602235289Sadrian default: 603250382Sadrian usage(&cfg, argv); 604235289Sadrian } 605235289Sadrian argc -= optind; 606235289Sadrian argv += optind; 607235289Sadrian cfg.fd = open(cfg.controlfile, O_RDONLY); 608235289Sadrian if (cfg.fd < 0) 609235289Sadrian err(EX_UNAVAILABLE, "Can't open control file: %s", cfg.controlfile); 610235289Sadrian if (ioctl(cfg.fd, IOETHERSWITCHGETINFO, &cfg.info) != 0) 611235289Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETINFO)"); 612250382Sadrian if (ioctl(cfg.fd, IOETHERSWITCHGETCONF, &cfg.conf) != 0) 613250382Sadrian err(EX_OSERR, "ioctl(IOETHERSWITCHGETCONF)"); 614235289Sadrian if (argc == 0) { 615235289Sadrian print_info(&cfg); 616235289Sadrian return (0); 617235289Sadrian } 618235289Sadrian cfg.mode = MODE_NONE; 619235289Sadrian while (argc > 0) { 620235289Sadrian switch(cfg.mode) { 621235289Sadrian case MODE_NONE: 622235289Sadrian if (strcmp(argv[0], "info") == 0) { 623235289Sadrian print_info(&cfg); 624235289Sadrian } else if (sscanf(argv[0], "port%d", &cfg.unit) == 1) { 625235289Sadrian if (cfg.unit < 0 || cfg.unit >= cfg.info.es_nports) 626255730Shiren errx(EX_USAGE, "port unit must be between 0 and %d", cfg.info.es_nports - 1); 627235289Sadrian newmode(&cfg, MODE_PORT); 628235289Sadrian } else if (sscanf(argv[0], "vlangroup%d", &cfg.unit) == 1) { 629235289Sadrian if (cfg.unit < 0 || cfg.unit >= cfg.info.es_nvlangroups) 630253568Sloos errx(EX_USAGE, 631253568Sloos "vlangroup unit must be between 0 and %d", 632253568Sloos cfg.info.es_nvlangroups - 1); 633235289Sadrian newmode(&cfg, MODE_VLANGROUP); 634250382Sadrian } else if (strcmp(argv[0], "config") == 0) { 635250382Sadrian newmode(&cfg, MODE_CONFIG); 636235289Sadrian } else if (strcmp(argv[0], "phy") == 0) { 637235289Sadrian newmode(&cfg, MODE_PHYREG); 638235289Sadrian } else if (strcmp(argv[0], "reg") == 0) { 639235289Sadrian newmode(&cfg, MODE_REGISTER); 640250382Sadrian } else if (strcmp(argv[0], "help") == 0) { 641250382Sadrian usage(&cfg, argv); 642235289Sadrian } else { 643235289Sadrian errx(EX_USAGE, "Unknown command \"%s\"", argv[0]); 644235289Sadrian } 645235289Sadrian break; 646235289Sadrian case MODE_PORT: 647250382Sadrian case MODE_CONFIG: 648235289Sadrian case MODE_VLANGROUP: 649235289Sadrian for(i=0; cmds[i].name != NULL; i++) { 650249748Sadrian if (cfg.mode == cmds[i].mode && strcmp(argv[0], cmds[i].name) == 0) { 651249748Sadrian if (argc < (cmds[i].args + 1)) { 652249748Sadrian printf("%s needs an argument\n", cmds[i].name); 653249748Sadrian break; 654249748Sadrian } 655235289Sadrian (cmds[i].f)(&cfg, argv); 656235289Sadrian argc -= cmds[i].args; 657235289Sadrian argv += cmds[i].args; 658235289Sadrian break; 659235289Sadrian } 660235289Sadrian } 661235289Sadrian if (cmds[i].name == NULL) { 662235289Sadrian newmode(&cfg, MODE_NONE); 663235289Sadrian continue; 664235289Sadrian } 665235289Sadrian break; 666235289Sadrian case MODE_REGISTER: 667235289Sadrian if (set_register(&cfg, argv[0]) != 0) { 668235289Sadrian newmode(&cfg, MODE_NONE); 669235289Sadrian continue; 670235289Sadrian } 671235289Sadrian break; 672235289Sadrian case MODE_PHYREG: 673235289Sadrian if (set_phyregister(&cfg, argv[0]) != 0) { 674235289Sadrian newmode(&cfg, MODE_NONE); 675235289Sadrian continue; 676235289Sadrian } 677235289Sadrian break; 678235289Sadrian } 679235289Sadrian argc--; 680235289Sadrian argv++; 681235289Sadrian } 682235289Sadrian /* switch back to command mode to print configuration for last command */ 683235289Sadrian newmode(&cfg, MODE_NONE); 684235289Sadrian close(cfg.fd); 685235289Sadrian return (0); 686235289Sadrian} 687235289Sadrian 688241720Sedstatic struct cmds cmds[] = { 689249752Sadrian { MODE_PORT, "pvid", 1, set_port_vid }, 690235289Sadrian { MODE_PORT, "media", 1, set_port_media }, 691235289Sadrian { MODE_PORT, "mediaopt", 1, set_port_mediaopt }, 692250382Sadrian { MODE_PORT, "addtag", 0, set_port_flag }, 693250382Sadrian { MODE_PORT, "-addtag", 0, set_port_flag }, 694250382Sadrian { MODE_PORT, "ingress", 0, set_port_flag }, 695250382Sadrian { MODE_PORT, "-ingress", 0, set_port_flag }, 696250382Sadrian { MODE_PORT, "striptag", 0, set_port_flag }, 697250382Sadrian { MODE_PORT, "-striptag", 0, set_port_flag }, 698250382Sadrian { MODE_PORT, "doubletag", 0, set_port_flag }, 699250382Sadrian { MODE_PORT, "-doubletag", 0, set_port_flag }, 700250382Sadrian { MODE_PORT, "firstlock", 0, set_port_flag }, 701250382Sadrian { MODE_PORT, "-firstlock", 0, set_port_flag }, 702250382Sadrian { MODE_PORT, "dropuntagged", 0, set_port_flag }, 703250382Sadrian { MODE_PORT, "-dropuntagged", 0, set_port_flag }, 704250382Sadrian { MODE_CONFIG, "vlan_mode", 1, set_vlan_mode }, 705235289Sadrian { MODE_VLANGROUP, "vlan", 1, set_vlangroup_vid }, 706235289Sadrian { MODE_VLANGROUP, "members", 1, set_vlangroup_members }, 707235289Sadrian { 0, NULL, 0, NULL } 708235289Sadrian}; 709