1270069b7SAdrian Chadd /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
4270069b7SAdrian Chadd * Copyright (c) 2011-2012 Stefan Bethke.
5270069b7SAdrian Chadd * All rights reserved.
6270069b7SAdrian Chadd *
7270069b7SAdrian Chadd * Redistribution and use in source and binary forms, with or without
8270069b7SAdrian Chadd * modification, are permitted provided that the following conditions
9270069b7SAdrian Chadd * are met:
10270069b7SAdrian Chadd * 1. Redistributions of source code must retain the above copyright
11270069b7SAdrian Chadd * notice, this list of conditions and the following disclaimer.
12270069b7SAdrian Chadd * 2. Redistributions in binary form must reproduce the above copyright
13270069b7SAdrian Chadd * notice, this list of conditions and the following disclaimer in the
14270069b7SAdrian Chadd * documentation and/or other materials provided with the distribution.
15270069b7SAdrian Chadd *
16270069b7SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17270069b7SAdrian Chadd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18270069b7SAdrian Chadd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19270069b7SAdrian Chadd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20270069b7SAdrian Chadd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21270069b7SAdrian Chadd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22270069b7SAdrian Chadd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23270069b7SAdrian Chadd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24270069b7SAdrian Chadd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25270069b7SAdrian Chadd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26270069b7SAdrian Chadd * SUCH DAMAGE.
27270069b7SAdrian Chadd */
28270069b7SAdrian Chadd
29270069b7SAdrian Chadd #include <sys/cdefs.h>
30270069b7SAdrian Chadd #include <ctype.h>
31270069b7SAdrian Chadd #include <err.h>
32270069b7SAdrian Chadd #include <errno.h>
33270069b7SAdrian Chadd #include <fcntl.h>
34270069b7SAdrian Chadd #include <stdio.h>
35270069b7SAdrian Chadd #include <stdlib.h>
36270069b7SAdrian Chadd #include <string.h>
37270069b7SAdrian Chadd #include <sysexits.h>
38270069b7SAdrian Chadd #include <unistd.h>
39270069b7SAdrian Chadd #include <sys/types.h>
40270069b7SAdrian Chadd #include <sys/ioctl.h>
41270069b7SAdrian Chadd #include <net/if.h>
42270069b7SAdrian Chadd #include <net/if_media.h>
43270069b7SAdrian Chadd #include <dev/etherswitch/etherswitch.h>
44270069b7SAdrian Chadd
45270069b7SAdrian Chadd int get_media_subtype(int, const char *);
46270069b7SAdrian Chadd int get_media_mode(int, const char *);
47270069b7SAdrian Chadd int get_media_options(int, const char *);
48270069b7SAdrian Chadd int lookup_media_word(struct ifmedia_description *, const char *);
49270069b7SAdrian Chadd void print_media_word(int, int);
50270069b7SAdrian Chadd void print_media_word_ifconfig(int);
51270069b7SAdrian Chadd
52270069b7SAdrian Chadd /* some constants */
53270069b7SAdrian Chadd #define IEEE802DOT1Q_VID_MAX 4094
54270069b7SAdrian Chadd #define IFMEDIAREQ_NULISTENTRIES 256
55270069b7SAdrian Chadd
56270069b7SAdrian Chadd enum cmdmode {
57270069b7SAdrian Chadd MODE_NONE = 0,
58270069b7SAdrian Chadd MODE_PORT,
59e6e5db84SAdrian Chadd MODE_CONFIG,
60270069b7SAdrian Chadd MODE_VLANGROUP,
61270069b7SAdrian Chadd MODE_REGISTER,
62138952cfSAdrian Chadd MODE_PHYREG,
63138952cfSAdrian Chadd MODE_ATU
64270069b7SAdrian Chadd };
65270069b7SAdrian Chadd
66270069b7SAdrian Chadd struct cfg {
67270069b7SAdrian Chadd int fd;
68270069b7SAdrian Chadd int verbose;
69270069b7SAdrian Chadd int mediatypes;
70270069b7SAdrian Chadd const char *controlfile;
71e6e5db84SAdrian Chadd etherswitch_conf_t conf;
72270069b7SAdrian Chadd etherswitch_info_t info;
73270069b7SAdrian Chadd enum cmdmode mode;
74270069b7SAdrian Chadd int unit;
75270069b7SAdrian Chadd };
76270069b7SAdrian Chadd
77270069b7SAdrian Chadd struct cmds {
78270069b7SAdrian Chadd enum cmdmode mode;
79270069b7SAdrian Chadd const char *name;
80270069b7SAdrian Chadd int args;
81138952cfSAdrian Chadd int (*f)(struct cfg *, int argc, char *argv[]);
82270069b7SAdrian Chadd };
83ae824d80SEd Schouten static struct cmds cmds[];
84270069b7SAdrian Chadd
851cec2c73SAdrian Chadd /* Must match the ETHERSWITCH_PORT_LED_* enum order */
861cec2c73SAdrian Chadd static const char *ledstyles[] = { "default", "on", "off", "blink", NULL };
87270069b7SAdrian Chadd
88e6e5db84SAdrian Chadd /*
89e6e5db84SAdrian Chadd * Print a value a la the %b format of the kernel's printf.
90e6e5db84SAdrian Chadd * Stolen from ifconfig.c.
91e6e5db84SAdrian Chadd */
92e6e5db84SAdrian Chadd static void
printb(const char * s,unsigned v,const char * bits)93e6e5db84SAdrian Chadd printb(const char *s, unsigned v, const char *bits)
94e6e5db84SAdrian Chadd {
95e6e5db84SAdrian Chadd int i, any = 0;
96e6e5db84SAdrian Chadd char c;
97e6e5db84SAdrian Chadd
98e6e5db84SAdrian Chadd if (bits && *bits == 8)
99e6e5db84SAdrian Chadd printf("%s=%o", s, v);
100e6e5db84SAdrian Chadd else
101e6e5db84SAdrian Chadd printf("%s=%x", s, v);
102e6e5db84SAdrian Chadd bits++;
103e6e5db84SAdrian Chadd if (bits) {
104e6e5db84SAdrian Chadd putchar('<');
105e6e5db84SAdrian Chadd while ((i = *bits++) != '\0') {
106e6e5db84SAdrian Chadd if (v & (1 << (i-1))) {
107e6e5db84SAdrian Chadd if (any)
108e6e5db84SAdrian Chadd putchar(',');
109e6e5db84SAdrian Chadd any = 1;
110e6e5db84SAdrian Chadd for (; (c = *bits) > 32; bits++)
111e6e5db84SAdrian Chadd putchar(c);
112e6e5db84SAdrian Chadd } else
113e6e5db84SAdrian Chadd for (; *bits > 32; bits++)
114e6e5db84SAdrian Chadd ;
115e6e5db84SAdrian Chadd }
116e6e5db84SAdrian Chadd putchar('>');
117e6e5db84SAdrian Chadd }
118e6e5db84SAdrian Chadd }
119270069b7SAdrian Chadd
120270069b7SAdrian Chadd static int
read_register(struct cfg * cfg,int r)121270069b7SAdrian Chadd read_register(struct cfg *cfg, int r)
122270069b7SAdrian Chadd {
123270069b7SAdrian Chadd struct etherswitch_reg er;
124270069b7SAdrian Chadd
125270069b7SAdrian Chadd er.reg = r;
126270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETREG, &er) != 0)
127270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETREG)");
128270069b7SAdrian Chadd return (er.val);
129270069b7SAdrian Chadd }
130270069b7SAdrian Chadd
131270069b7SAdrian Chadd static void
write_register(struct cfg * cfg,int r,int v)132270069b7SAdrian Chadd write_register(struct cfg *cfg, int r, int v)
133270069b7SAdrian Chadd {
134270069b7SAdrian Chadd struct etherswitch_reg er;
135270069b7SAdrian Chadd
136270069b7SAdrian Chadd er.reg = r;
137270069b7SAdrian Chadd er.val = v;
138270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETREG, &er) != 0)
139270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETREG)");
140270069b7SAdrian Chadd }
141270069b7SAdrian Chadd
142270069b7SAdrian Chadd static int
read_phyregister(struct cfg * cfg,int phy,int reg)143270069b7SAdrian Chadd read_phyregister(struct cfg *cfg, int phy, int reg)
144270069b7SAdrian Chadd {
145270069b7SAdrian Chadd struct etherswitch_phyreg er;
146270069b7SAdrian Chadd
147270069b7SAdrian Chadd er.phy = phy;
148270069b7SAdrian Chadd er.reg = reg;
149270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETPHYREG, &er) != 0)
150270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETPHYREG)");
151270069b7SAdrian Chadd return (er.val);
152270069b7SAdrian Chadd }
153270069b7SAdrian Chadd
154270069b7SAdrian Chadd static void
write_phyregister(struct cfg * cfg,int phy,int reg,int val)155270069b7SAdrian Chadd write_phyregister(struct cfg *cfg, int phy, int reg, int val)
156270069b7SAdrian Chadd {
157270069b7SAdrian Chadd struct etherswitch_phyreg er;
158270069b7SAdrian Chadd
159270069b7SAdrian Chadd er.phy = phy;
160270069b7SAdrian Chadd er.reg = reg;
161270069b7SAdrian Chadd er.val = val;
162270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETPHYREG, &er) != 0)
163270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETPHYREG)");
164270069b7SAdrian Chadd }
165270069b7SAdrian Chadd
166138952cfSAdrian Chadd static int
set_port_vid(struct cfg * cfg,int argc,char * argv[])167138952cfSAdrian Chadd set_port_vid(struct cfg *cfg, int argc, char *argv[])
168270069b7SAdrian Chadd {
169270069b7SAdrian Chadd int v;
170270069b7SAdrian Chadd etherswitch_port_t p;
171270069b7SAdrian Chadd
172138952cfSAdrian Chadd if (argc < 2)
173138952cfSAdrian Chadd return (-1);
174138952cfSAdrian Chadd
175270069b7SAdrian Chadd v = strtol(argv[1], NULL, 0);
176a3219359SAdrian Chadd if (v < 0 || v > IEEE802DOT1Q_VID_MAX)
177a3219359SAdrian Chadd errx(EX_USAGE, "pvid must be between 0 and %d",
178a3219359SAdrian Chadd IEEE802DOT1Q_VID_MAX);
179e1d63790SAdrian Chadd bzero(&p, sizeof(p));
180270069b7SAdrian Chadd p.es_port = cfg->unit;
181270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0)
182270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)");
183a3219359SAdrian Chadd p.es_pvid = v;
184270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0)
185270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)");
186138952cfSAdrian Chadd return (0);
187270069b7SAdrian Chadd }
188270069b7SAdrian Chadd
189138952cfSAdrian Chadd static int
set_port_flag(struct cfg * cfg,int argc,char * argv[])190138952cfSAdrian Chadd set_port_flag(struct cfg *cfg, int argc, char *argv[])
191e6e5db84SAdrian Chadd {
192e6e5db84SAdrian Chadd char *flag;
193e6e5db84SAdrian Chadd int n;
194e6e5db84SAdrian Chadd uint32_t f;
195e6e5db84SAdrian Chadd etherswitch_port_t p;
196e6e5db84SAdrian Chadd
197138952cfSAdrian Chadd if (argc < 1)
198138952cfSAdrian Chadd return (-1);
199138952cfSAdrian Chadd
200e6e5db84SAdrian Chadd n = 0;
201e6e5db84SAdrian Chadd f = 0;
202e6e5db84SAdrian Chadd flag = argv[0];
203e6e5db84SAdrian Chadd if (strcmp(flag, "none") != 0) {
204e6e5db84SAdrian Chadd if (*flag == '-') {
205e6e5db84SAdrian Chadd n++;
206e6e5db84SAdrian Chadd flag++;
207e6e5db84SAdrian Chadd }
208e6e5db84SAdrian Chadd if (strcasecmp(flag, "striptag") == 0)
209e6e5db84SAdrian Chadd f = ETHERSWITCH_PORT_STRIPTAG;
210e6e5db84SAdrian Chadd else if (strcasecmp(flag, "addtag") == 0)
211e6e5db84SAdrian Chadd f = ETHERSWITCH_PORT_ADDTAG;
212e6e5db84SAdrian Chadd else if (strcasecmp(flag, "firstlock") == 0)
213e6e5db84SAdrian Chadd f = ETHERSWITCH_PORT_FIRSTLOCK;
2144e4cedb0SLuiz Otavio O Souza else if (strcasecmp(flag, "droptagged") == 0)
2154e4cedb0SLuiz Otavio O Souza f = ETHERSWITCH_PORT_DROPTAGGED;
216e6e5db84SAdrian Chadd else if (strcasecmp(flag, "dropuntagged") == 0)
217e6e5db84SAdrian Chadd f = ETHERSWITCH_PORT_DROPUNTAGGED;
218e6e5db84SAdrian Chadd else if (strcasecmp(flag, "doubletag") == 0)
219e6e5db84SAdrian Chadd f = ETHERSWITCH_PORT_DOUBLE_TAG;
220e6e5db84SAdrian Chadd else if (strcasecmp(flag, "ingress") == 0)
221e6e5db84SAdrian Chadd f = ETHERSWITCH_PORT_INGRESS;
222f5b29d0fSKornel Duleba else if (strcasecmp(flag, "striptagingress") == 0)
223f5b29d0fSKornel Duleba f = ETHERSWITCH_PORT_STRIPTAGINGRESS;
224e6e5db84SAdrian Chadd }
225e6e5db84SAdrian Chadd bzero(&p, sizeof(p));
226e6e5db84SAdrian Chadd p.es_port = cfg->unit;
227e6e5db84SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0)
228e6e5db84SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)");
229e6e5db84SAdrian Chadd if (n)
230e6e5db84SAdrian Chadd p.es_flags &= ~f;
231e6e5db84SAdrian Chadd else
232e6e5db84SAdrian Chadd p.es_flags |= f;
233e6e5db84SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0)
234e6e5db84SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)");
235138952cfSAdrian Chadd return (0);
236e6e5db84SAdrian Chadd }
237e6e5db84SAdrian Chadd
238138952cfSAdrian Chadd static int
set_port_media(struct cfg * cfg,int argc,char * argv[])239138952cfSAdrian Chadd set_port_media(struct cfg *cfg, int argc, char *argv[])
240270069b7SAdrian Chadd {
241270069b7SAdrian Chadd etherswitch_port_t p;
242270069b7SAdrian Chadd int ifm_ulist[IFMEDIAREQ_NULISTENTRIES];
243270069b7SAdrian Chadd int subtype;
244270069b7SAdrian Chadd
245138952cfSAdrian Chadd if (argc < 2)
246138952cfSAdrian Chadd return (-1);
247138952cfSAdrian Chadd
248270069b7SAdrian Chadd bzero(&p, sizeof(p));
249270069b7SAdrian Chadd p.es_port = cfg->unit;
250270069b7SAdrian Chadd p.es_ifmr.ifm_ulist = ifm_ulist;
251270069b7SAdrian Chadd p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES;
252270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0)
253270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)");
254a48d677fSLuiz Otavio O Souza if (p.es_ifmr.ifm_count == 0)
255138952cfSAdrian Chadd return (0);
256270069b7SAdrian Chadd subtype = get_media_subtype(IFM_TYPE(ifm_ulist[0]), argv[1]);
257270069b7SAdrian Chadd p.es_ifr.ifr_media = (p.es_ifmr.ifm_current & IFM_IMASK) |
258270069b7SAdrian Chadd IFM_TYPE(ifm_ulist[0]) | subtype;
259270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0)
260270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)");
261138952cfSAdrian Chadd return (0);
262270069b7SAdrian Chadd }
263270069b7SAdrian Chadd
264138952cfSAdrian Chadd static int
set_port_mediaopt(struct cfg * cfg,int argc,char * argv[])265138952cfSAdrian Chadd set_port_mediaopt(struct cfg *cfg, int argc, char *argv[])
266270069b7SAdrian Chadd {
267270069b7SAdrian Chadd etherswitch_port_t p;
268270069b7SAdrian Chadd int ifm_ulist[IFMEDIAREQ_NULISTENTRIES];
269270069b7SAdrian Chadd int options;
270270069b7SAdrian Chadd
271138952cfSAdrian Chadd if (argc < 2)
272138952cfSAdrian Chadd return (-1);
273138952cfSAdrian Chadd
274270069b7SAdrian Chadd bzero(&p, sizeof(p));
275270069b7SAdrian Chadd p.es_port = cfg->unit;
276270069b7SAdrian Chadd p.es_ifmr.ifm_ulist = ifm_ulist;
277270069b7SAdrian Chadd p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES;
278270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0)
279270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)");
280270069b7SAdrian Chadd options = get_media_options(IFM_TYPE(ifm_ulist[0]), argv[1]);
281270069b7SAdrian Chadd if (options == -1)
282270069b7SAdrian Chadd errx(EX_USAGE, "invalid media options \"%s\"", argv[1]);
283270069b7SAdrian Chadd if (options & IFM_HDX) {
284270069b7SAdrian Chadd p.es_ifr.ifr_media &= ~IFM_FDX;
285270069b7SAdrian Chadd options &= ~IFM_HDX;
286270069b7SAdrian Chadd }
287270069b7SAdrian Chadd p.es_ifr.ifr_media |= options;
288270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0)
289270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)");
290138952cfSAdrian Chadd return (0);
291270069b7SAdrian Chadd }
292270069b7SAdrian Chadd
293138952cfSAdrian Chadd static int
set_port_led(struct cfg * cfg,int argc,char * argv[])294138952cfSAdrian Chadd set_port_led(struct cfg *cfg, int argc, char *argv[])
2951cec2c73SAdrian Chadd {
2961cec2c73SAdrian Chadd etherswitch_port_t p;
2971cec2c73SAdrian Chadd int led;
2981cec2c73SAdrian Chadd int i;
2991cec2c73SAdrian Chadd
300138952cfSAdrian Chadd if (argc < 3)
301138952cfSAdrian Chadd return (-1);
302138952cfSAdrian Chadd
3031cec2c73SAdrian Chadd bzero(&p, sizeof(p));
3041cec2c73SAdrian Chadd p.es_port = cfg->unit;
3051cec2c73SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0)
3061cec2c73SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)");
3071cec2c73SAdrian Chadd
3081cec2c73SAdrian Chadd led = strtol(argv[1], NULL, 0);
3091cec2c73SAdrian Chadd if (led < 1 || led > p.es_nleds)
3101cec2c73SAdrian Chadd errx(EX_USAGE, "invalid led number %s; must be between 1 and %d",
3111cec2c73SAdrian Chadd argv[1], p.es_nleds);
3121cec2c73SAdrian Chadd
3131cec2c73SAdrian Chadd led--;
3141cec2c73SAdrian Chadd
3151cec2c73SAdrian Chadd for (i=0; ledstyles[i] != NULL; i++) {
3161cec2c73SAdrian Chadd if (strcmp(argv[2], ledstyles[i]) == 0) {
3171cec2c73SAdrian Chadd p.es_led[led] = i;
3181cec2c73SAdrian Chadd break;
3191cec2c73SAdrian Chadd }
3201cec2c73SAdrian Chadd }
3211cec2c73SAdrian Chadd if (ledstyles[i] == NULL)
3221cec2c73SAdrian Chadd errx(EX_USAGE, "invalid led style \"%s\"", argv[2]);
3231cec2c73SAdrian Chadd
3241cec2c73SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0)
3251cec2c73SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)");
326138952cfSAdrian Chadd
327138952cfSAdrian Chadd return (0);
3281cec2c73SAdrian Chadd }
3291cec2c73SAdrian Chadd
330138952cfSAdrian Chadd static int
set_vlangroup_vid(struct cfg * cfg,int argc,char * argv[])331138952cfSAdrian Chadd set_vlangroup_vid(struct cfg *cfg, int argc, char *argv[])
332270069b7SAdrian Chadd {
333270069b7SAdrian Chadd int v;
334270069b7SAdrian Chadd etherswitch_vlangroup_t vg;
335270069b7SAdrian Chadd
336138952cfSAdrian Chadd if (argc < 2)
337138952cfSAdrian Chadd return (-1);
338138952cfSAdrian Chadd
33908f58fe4SLuiz Otavio O Souza memset(&vg, 0, sizeof(vg));
340270069b7SAdrian Chadd v = strtol(argv[1], NULL, 0);
341ba5ff393SHiren Panchasara if (v < 0 || v > IEEE802DOT1Q_VID_MAX)
342270069b7SAdrian Chadd errx(EX_USAGE, "vlan must be between 0 and %d", IEEE802DOT1Q_VID_MAX);
343270069b7SAdrian Chadd vg.es_vlangroup = cfg->unit;
344270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0)
345270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)");
346270069b7SAdrian Chadd vg.es_vid = v;
347270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETVLANGROUP, &vg) != 0)
348270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETVLANGROUP)");
349138952cfSAdrian Chadd return (0);
350270069b7SAdrian Chadd }
351270069b7SAdrian Chadd
352138952cfSAdrian Chadd static int
set_vlangroup_members(struct cfg * cfg,int argc,char * argv[])353138952cfSAdrian Chadd set_vlangroup_members(struct cfg *cfg, int argc, char *argv[])
354270069b7SAdrian Chadd {
355270069b7SAdrian Chadd etherswitch_vlangroup_t vg;
356270069b7SAdrian Chadd int member, untagged;
357270069b7SAdrian Chadd char *c, *d;
358270069b7SAdrian Chadd int v;
359270069b7SAdrian Chadd
360138952cfSAdrian Chadd if (argc < 2)
361138952cfSAdrian Chadd return (-1);
362138952cfSAdrian Chadd
363270069b7SAdrian Chadd member = untagged = 0;
36408f58fe4SLuiz Otavio O Souza memset(&vg, 0, sizeof(vg));
365270069b7SAdrian Chadd if (strcmp(argv[1], "none") != 0) {
366270069b7SAdrian Chadd for (c=argv[1]; *c; c=d) {
367270069b7SAdrian Chadd v = strtol(c, &d, 0);
368270069b7SAdrian Chadd if (d == c)
369270069b7SAdrian Chadd break;
370270069b7SAdrian Chadd if (v < 0 || v >= cfg->info.es_nports)
371270069b7SAdrian Chadd errx(EX_USAGE, "Member port must be between 0 and %d", cfg->info.es_nports-1);
372270069b7SAdrian Chadd if (d[0] == ',' || d[0] == '\0' ||
373270069b7SAdrian Chadd ((d[0] == 't' || d[0] == 'T') && (d[1] == ',' || d[1] == '\0'))) {
374270069b7SAdrian Chadd if (d[0] == 't' || d[0] == 'T') {
375270069b7SAdrian Chadd untagged &= ~ETHERSWITCH_PORTMASK(v);
376270069b7SAdrian Chadd d++;
377270069b7SAdrian Chadd } else
378270069b7SAdrian Chadd untagged |= ETHERSWITCH_PORTMASK(v);
379270069b7SAdrian Chadd member |= ETHERSWITCH_PORTMASK(v);
380270069b7SAdrian Chadd d++;
381270069b7SAdrian Chadd } else
382270069b7SAdrian Chadd errx(EX_USAGE, "Invalid members specification \"%s\"", d);
383270069b7SAdrian Chadd }
384270069b7SAdrian Chadd }
385270069b7SAdrian Chadd vg.es_vlangroup = cfg->unit;
386270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0)
387270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)");
388270069b7SAdrian Chadd vg.es_member_ports = member;
389270069b7SAdrian Chadd vg.es_untagged_ports = untagged;
390270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETVLANGROUP, &vg) != 0)
391270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETVLANGROUP)");
392138952cfSAdrian Chadd return (0);
393270069b7SAdrian Chadd }
394270069b7SAdrian Chadd
395270069b7SAdrian Chadd static int
set_register(struct cfg * cfg,char * arg)396270069b7SAdrian Chadd set_register(struct cfg *cfg, char *arg)
397270069b7SAdrian Chadd {
398270069b7SAdrian Chadd int a, v;
399270069b7SAdrian Chadd char *c;
400270069b7SAdrian Chadd
401270069b7SAdrian Chadd a = strtol(arg, &c, 0);
402270069b7SAdrian Chadd if (c==arg)
403270069b7SAdrian Chadd return (1);
404270069b7SAdrian Chadd if (*c == '=') {
4051cec2c73SAdrian Chadd v = strtoul(c+1, NULL, 0);
406270069b7SAdrian Chadd write_register(cfg, a, v);
407270069b7SAdrian Chadd }
4081cec2c73SAdrian Chadd printf("\treg 0x%04x=0x%08x\n", a, read_register(cfg, a));
409270069b7SAdrian Chadd return (0);
410270069b7SAdrian Chadd }
411270069b7SAdrian Chadd
412270069b7SAdrian Chadd static int
set_phyregister(struct cfg * cfg,char * arg)413270069b7SAdrian Chadd set_phyregister(struct cfg *cfg, char *arg)
414270069b7SAdrian Chadd {
415270069b7SAdrian Chadd int phy, reg, val;
416270069b7SAdrian Chadd char *c, *d;
417270069b7SAdrian Chadd
418270069b7SAdrian Chadd phy = strtol(arg, &c, 0);
419270069b7SAdrian Chadd if (c==arg)
420270069b7SAdrian Chadd return (1);
421270069b7SAdrian Chadd if (*c != '.')
422270069b7SAdrian Chadd return (1);
423270069b7SAdrian Chadd d = c+1;
424270069b7SAdrian Chadd reg = strtol(d, &c, 0);
425270069b7SAdrian Chadd if (d == c)
426270069b7SAdrian Chadd return (1);
427270069b7SAdrian Chadd if (*c == '=') {
4281cec2c73SAdrian Chadd val = strtoul(c+1, NULL, 0);
429270069b7SAdrian Chadd write_phyregister(cfg, phy, reg, val);
430270069b7SAdrian Chadd }
431270069b7SAdrian Chadd printf("\treg %d.0x%02x=0x%04x\n", phy, reg, read_phyregister(cfg, phy, reg));
432270069b7SAdrian Chadd return (0);
433270069b7SAdrian Chadd }
434270069b7SAdrian Chadd
435138952cfSAdrian Chadd static int
set_vlan_mode(struct cfg * cfg,int argc,char * argv[])436138952cfSAdrian Chadd set_vlan_mode(struct cfg *cfg, int argc, char *argv[])
437e6e5db84SAdrian Chadd {
438e6e5db84SAdrian Chadd etherswitch_conf_t conf;
439e6e5db84SAdrian Chadd
440138952cfSAdrian Chadd if (argc < 2)
441138952cfSAdrian Chadd return (-1);
442138952cfSAdrian Chadd
443e6e5db84SAdrian Chadd bzero(&conf, sizeof(conf));
444e6e5db84SAdrian Chadd conf.cmd = ETHERSWITCH_CONF_VLAN_MODE;
445e6e5db84SAdrian Chadd if (strcasecmp(argv[1], "isl") == 0)
446e6e5db84SAdrian Chadd conf.vlan_mode = ETHERSWITCH_VLAN_ISL;
447e6e5db84SAdrian Chadd else if (strcasecmp(argv[1], "port") == 0)
448e6e5db84SAdrian Chadd conf.vlan_mode = ETHERSWITCH_VLAN_PORT;
449e6e5db84SAdrian Chadd else if (strcasecmp(argv[1], "dot1q") == 0)
450e6e5db84SAdrian Chadd conf.vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
451e6e5db84SAdrian Chadd else if (strcasecmp(argv[1], "dot1q4k") == 0)
452e6e5db84SAdrian Chadd conf.vlan_mode = ETHERSWITCH_VLAN_DOT1Q_4K;
453e6e5db84SAdrian Chadd else if (strcasecmp(argv[1], "qinq") == 0)
454e6e5db84SAdrian Chadd conf.vlan_mode = ETHERSWITCH_VLAN_DOUBLE_TAG;
455e6e5db84SAdrian Chadd else
456e6e5db84SAdrian Chadd conf.vlan_mode = 0;
457e6e5db84SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHSETCONF, &conf) != 0)
458e6e5db84SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHSETCONF)");
459138952cfSAdrian Chadd
460138952cfSAdrian Chadd return (0);
461138952cfSAdrian Chadd }
462138952cfSAdrian Chadd
463138952cfSAdrian Chadd static int
atu_flush(struct cfg * cfg,int argc,char * argv[])464138952cfSAdrian Chadd atu_flush(struct cfg *cfg, int argc, char *argv[])
465138952cfSAdrian Chadd {
466138952cfSAdrian Chadd etherswitch_portid_t p;
467138952cfSAdrian Chadd int i, r;
468138952cfSAdrian Chadd
469138952cfSAdrian Chadd bzero(&p, sizeof(p));
470138952cfSAdrian Chadd
471138952cfSAdrian Chadd /* note: argv[0] is "flush" */
472138952cfSAdrian Chadd if (argc > 2 && strcasecmp(argv[1], "port") == 0) {
473138952cfSAdrian Chadd p.es_port = atoi(argv[2]);
474138952cfSAdrian Chadd i = IOETHERSWITCHFLUSHPORT;
475138952cfSAdrian Chadd r = 3;
476138952cfSAdrian Chadd } else if (argc > 1 && strcasecmp(argv[1], "all") == 0) {
477138952cfSAdrian Chadd p.es_port = 0;
478138952cfSAdrian Chadd r = 2;
479138952cfSAdrian Chadd i = IOETHERSWITCHFLUSHALL;
480138952cfSAdrian Chadd } else {
481138952cfSAdrian Chadd fprintf(stderr,
482138952cfSAdrian Chadd "%s: invalid verb (port <x> or all) (got %s)\n",
483138952cfSAdrian Chadd __func__, argv[1]);
484138952cfSAdrian Chadd return (-1);
485138952cfSAdrian Chadd }
486138952cfSAdrian Chadd
487138952cfSAdrian Chadd if (ioctl(cfg->fd, i, &p) != 0)
488138952cfSAdrian Chadd err(EX_OSERR, "ioctl(ATU flush (ioctl %d, port %d))",
489138952cfSAdrian Chadd i, p.es_port);
490138952cfSAdrian Chadd return (r);
491138952cfSAdrian Chadd }
492138952cfSAdrian Chadd
493138952cfSAdrian Chadd static int
atu_dump(struct cfg * cfg,int argc,char * argv[])494138952cfSAdrian Chadd atu_dump(struct cfg *cfg, int argc, char *argv[])
495138952cfSAdrian Chadd {
496138952cfSAdrian Chadd etherswitch_atu_table_t p;
497138952cfSAdrian Chadd etherswitch_atu_entry_t e;
498138952cfSAdrian Chadd uint32_t i;
499138952cfSAdrian Chadd
500138952cfSAdrian Chadd (void) argc;
501138952cfSAdrian Chadd (void) argv;
502138952cfSAdrian Chadd
503138952cfSAdrian Chadd /* Note: argv[0] is "dump" */
504138952cfSAdrian Chadd bzero(&p, sizeof(p));
505138952cfSAdrian Chadd
506138952cfSAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETTABLE, &p) != 0)
507138952cfSAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETTABLE)");
508138952cfSAdrian Chadd
509138952cfSAdrian Chadd /* And now, iterate to get entries */
510138952cfSAdrian Chadd for (i = 0; i < p.es_nitems; i++) {
511138952cfSAdrian Chadd bzero(&e, sizeof(e));
512138952cfSAdrian Chadd e.id = i;
513138952cfSAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETTABLEENTRY, &e) != 0)
514138952cfSAdrian Chadd break;
515138952cfSAdrian Chadd
516138952cfSAdrian Chadd printf(" [%d] %s: portmask 0x%08x\n", i,
517138952cfSAdrian Chadd ether_ntoa((void *) &e.es_macaddr),
518138952cfSAdrian Chadd e.es_portmask);
519138952cfSAdrian Chadd }
520138952cfSAdrian Chadd
521138952cfSAdrian Chadd return (1);
522e6e5db84SAdrian Chadd }
523e6e5db84SAdrian Chadd
524e6e5db84SAdrian Chadd static void
print_config(struct cfg * cfg)525e6e5db84SAdrian Chadd print_config(struct cfg *cfg)
526e6e5db84SAdrian Chadd {
527e6e5db84SAdrian Chadd const char *c;
528e6e5db84SAdrian Chadd
529e6e5db84SAdrian Chadd /* Get the device name. */
530e6e5db84SAdrian Chadd c = strrchr(cfg->controlfile, '/');
531e6e5db84SAdrian Chadd if (c != NULL)
532e6e5db84SAdrian Chadd c = c + 1;
533e6e5db84SAdrian Chadd else
534e6e5db84SAdrian Chadd c = cfg->controlfile;
535e6e5db84SAdrian Chadd
536e6e5db84SAdrian Chadd /* Print VLAN mode. */
537e6e5db84SAdrian Chadd if (cfg->conf.cmd & ETHERSWITCH_CONF_VLAN_MODE) {
538e6e5db84SAdrian Chadd printf("%s: VLAN mode: ", c);
539e6e5db84SAdrian Chadd switch (cfg->conf.vlan_mode) {
540e6e5db84SAdrian Chadd case ETHERSWITCH_VLAN_ISL:
541e6e5db84SAdrian Chadd printf("ISL\n");
542e6e5db84SAdrian Chadd break;
543e6e5db84SAdrian Chadd case ETHERSWITCH_VLAN_PORT:
544e6e5db84SAdrian Chadd printf("PORT\n");
545e6e5db84SAdrian Chadd break;
546e6e5db84SAdrian Chadd case ETHERSWITCH_VLAN_DOT1Q:
547e6e5db84SAdrian Chadd printf("DOT1Q\n");
548e6e5db84SAdrian Chadd break;
549e6e5db84SAdrian Chadd case ETHERSWITCH_VLAN_DOT1Q_4K:
550e6e5db84SAdrian Chadd printf("DOT1Q4K\n");
551e6e5db84SAdrian Chadd break;
552e6e5db84SAdrian Chadd case ETHERSWITCH_VLAN_DOUBLE_TAG:
553e6e5db84SAdrian Chadd printf("QinQ\n");
554e6e5db84SAdrian Chadd break;
555e6e5db84SAdrian Chadd default:
556e6e5db84SAdrian Chadd printf("none\n");
557e6e5db84SAdrian Chadd }
558e6e5db84SAdrian Chadd }
55993e98f5fSAdrian Chadd
56093e98f5fSAdrian Chadd /* Print switch MAC address. */
56193e98f5fSAdrian Chadd if (cfg->conf.cmd & ETHERSWITCH_CONF_SWITCH_MACADDR) {
56293e98f5fSAdrian Chadd printf("%s: Switch MAC address: %s\n",
56393e98f5fSAdrian Chadd c,
56493e98f5fSAdrian Chadd ether_ntoa(&cfg->conf.switch_macaddr));
56593e98f5fSAdrian Chadd }
566e6e5db84SAdrian Chadd }
567e6e5db84SAdrian Chadd
568e6e5db84SAdrian Chadd static void
print_port(struct cfg * cfg,int port)569270069b7SAdrian Chadd print_port(struct cfg *cfg, int port)
570270069b7SAdrian Chadd {
571270069b7SAdrian Chadd etherswitch_port_t p;
572270069b7SAdrian Chadd int ifm_ulist[IFMEDIAREQ_NULISTENTRIES];
573270069b7SAdrian Chadd int i;
574270069b7SAdrian Chadd
575270069b7SAdrian Chadd bzero(&p, sizeof(p));
576270069b7SAdrian Chadd p.es_port = port;
577270069b7SAdrian Chadd p.es_ifmr.ifm_ulist = ifm_ulist;
578270069b7SAdrian Chadd p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES;
579270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0)
580270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)");
581270069b7SAdrian Chadd printf("port%d:\n", port);
582e6e5db84SAdrian Chadd if (cfg->conf.vlan_mode == ETHERSWITCH_VLAN_DOT1Q)
583a3219359SAdrian Chadd printf("\tpvid: %d\n", p.es_pvid);
584e6e5db84SAdrian Chadd printb("\tflags", p.es_flags, ETHERSWITCH_PORT_FLAGS_BITS);
585e6e5db84SAdrian Chadd printf("\n");
5861cec2c73SAdrian Chadd if (p.es_nleds) {
5871cec2c73SAdrian Chadd printf("\tled: ");
5881cec2c73SAdrian Chadd for (i = 0; i < p.es_nleds; i++) {
5891cec2c73SAdrian Chadd printf("%d:%s%s", i+1, ledstyles[p.es_led[i]], (i==p.es_nleds-1)?"":" ");
5901cec2c73SAdrian Chadd }
5911cec2c73SAdrian Chadd printf("\n");
5921cec2c73SAdrian Chadd }
593270069b7SAdrian Chadd printf("\tmedia: ");
594270069b7SAdrian Chadd print_media_word(p.es_ifmr.ifm_current, 1);
595270069b7SAdrian Chadd if (p.es_ifmr.ifm_active != p.es_ifmr.ifm_current) {
596270069b7SAdrian Chadd putchar(' ');
597270069b7SAdrian Chadd putchar('(');
598270069b7SAdrian Chadd print_media_word(p.es_ifmr.ifm_active, 0);
599270069b7SAdrian Chadd putchar(')');
600270069b7SAdrian Chadd }
601270069b7SAdrian Chadd putchar('\n');
602270069b7SAdrian Chadd printf("\tstatus: %s\n", (p.es_ifmr.ifm_status & IFM_ACTIVE) != 0 ? "active" : "no carrier");
603270069b7SAdrian Chadd if (cfg->mediatypes) {
604270069b7SAdrian Chadd printf("\tsupported media:\n");
605270069b7SAdrian Chadd if (p.es_ifmr.ifm_count > IFMEDIAREQ_NULISTENTRIES)
606270069b7SAdrian Chadd p.es_ifmr.ifm_count = IFMEDIAREQ_NULISTENTRIES;
607270069b7SAdrian Chadd for (i=0; i<p.es_ifmr.ifm_count; i++) {
608270069b7SAdrian Chadd printf("\t\tmedia ");
609270069b7SAdrian Chadd print_media_word(ifm_ulist[i], 0);
610270069b7SAdrian Chadd putchar('\n');
611270069b7SAdrian Chadd }
612270069b7SAdrian Chadd }
613270069b7SAdrian Chadd }
614270069b7SAdrian Chadd
615270069b7SAdrian Chadd static void
print_vlangroup(struct cfg * cfg,int vlangroup)616270069b7SAdrian Chadd print_vlangroup(struct cfg *cfg, int vlangroup)
617270069b7SAdrian Chadd {
618270069b7SAdrian Chadd etherswitch_vlangroup_t vg;
619270069b7SAdrian Chadd int i, comma;
620270069b7SAdrian Chadd
621270069b7SAdrian Chadd vg.es_vlangroup = vlangroup;
622270069b7SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0)
623270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)");
624cc320e37SLuiz Otavio O Souza if ((vg.es_vid & ETHERSWITCH_VID_VALID) == 0)
625270069b7SAdrian Chadd return;
626cc320e37SLuiz Otavio O Souza vg.es_vid &= ETHERSWITCH_VID_MASK;
627270069b7SAdrian Chadd printf("vlangroup%d:\n", vlangroup);
628e6e5db84SAdrian Chadd if (cfg->conf.vlan_mode == ETHERSWITCH_VLAN_PORT)
629e6e5db84SAdrian Chadd printf("\tport: %d\n", vg.es_vid);
630e6e5db84SAdrian Chadd else
631270069b7SAdrian Chadd printf("\tvlan: %d\n", vg.es_vid);
632270069b7SAdrian Chadd printf("\tmembers ");
633270069b7SAdrian Chadd comma = 0;
634270069b7SAdrian Chadd if (vg.es_member_ports != 0)
635270069b7SAdrian Chadd for (i=0; i<cfg->info.es_nports; i++) {
636270069b7SAdrian Chadd if ((vg.es_member_ports & ETHERSWITCH_PORTMASK(i)) != 0) {
637270069b7SAdrian Chadd if (comma)
638270069b7SAdrian Chadd printf(",");
639270069b7SAdrian Chadd printf("%d", i);
640270069b7SAdrian Chadd if ((vg.es_untagged_ports & ETHERSWITCH_PORTMASK(i)) == 0)
641270069b7SAdrian Chadd printf("t");
642270069b7SAdrian Chadd comma = 1;
643270069b7SAdrian Chadd }
644270069b7SAdrian Chadd }
645270069b7SAdrian Chadd else
646270069b7SAdrian Chadd printf("none");
647270069b7SAdrian Chadd printf("\n");
648270069b7SAdrian Chadd }
649270069b7SAdrian Chadd
650270069b7SAdrian Chadd static void
print_info(struct cfg * cfg)651270069b7SAdrian Chadd print_info(struct cfg *cfg)
652270069b7SAdrian Chadd {
653270069b7SAdrian Chadd const char *c;
654270069b7SAdrian Chadd int i;
655270069b7SAdrian Chadd
656270069b7SAdrian Chadd c = strrchr(cfg->controlfile, '/');
657270069b7SAdrian Chadd if (c != NULL)
658270069b7SAdrian Chadd c = c + 1;
659270069b7SAdrian Chadd else
660270069b7SAdrian Chadd c = cfg->controlfile;
661e6e5db84SAdrian Chadd if (cfg->verbose) {
662e6e5db84SAdrian Chadd printf("%s: %s with %d ports and %d VLAN groups\n", c,
663e6e5db84SAdrian Chadd cfg->info.es_name, cfg->info.es_nports,
664e6e5db84SAdrian Chadd cfg->info.es_nvlangroups);
665e6e5db84SAdrian Chadd printf("%s: ", c);
666e6e5db84SAdrian Chadd printb("VLAN capabilities", cfg->info.es_vlan_caps,
667e6e5db84SAdrian Chadd ETHERSWITCH_VLAN_CAPS_BITS);
668e6e5db84SAdrian Chadd printf("\n");
669e6e5db84SAdrian Chadd }
670e6e5db84SAdrian Chadd print_config(cfg);
671270069b7SAdrian Chadd for (i=0; i<cfg->info.es_nports; i++) {
672270069b7SAdrian Chadd print_port(cfg, i);
673270069b7SAdrian Chadd }
674270069b7SAdrian Chadd for (i=0; i<cfg->info.es_nvlangroups; i++) {
675270069b7SAdrian Chadd print_vlangroup(cfg, i);
676270069b7SAdrian Chadd }
677270069b7SAdrian Chadd }
678270069b7SAdrian Chadd
679270069b7SAdrian Chadd static void
usage(struct cfg * cfg __unused,char * argv[]__unused)680e6e5db84SAdrian Chadd usage(struct cfg *cfg __unused, char *argv[] __unused)
681270069b7SAdrian Chadd {
682270069b7SAdrian Chadd fprintf(stderr, "usage: etherswitchctl\n");
683e6e5db84SAdrian Chadd fprintf(stderr, "\tetherswitchcfg [-f control file] info\n");
684e6e5db84SAdrian Chadd fprintf(stderr, "\tetherswitchcfg [-f control file] config "
685e6e5db84SAdrian Chadd "command parameter\n");
686e6e5db84SAdrian Chadd fprintf(stderr, "\t\tconfig commands: vlan_mode\n");
687e6e5db84SAdrian Chadd fprintf(stderr, "\tetherswitchcfg [-f control file] phy "
688e6e5db84SAdrian Chadd "phy.register[=value]\n");
689e6e5db84SAdrian Chadd fprintf(stderr, "\tetherswitchcfg [-f control file] portX "
690e6e5db84SAdrian Chadd "[flags] command parameter\n");
6911cec2c73SAdrian Chadd fprintf(stderr, "\t\tport commands: pvid, media, mediaopt, led\n");
692e6e5db84SAdrian Chadd fprintf(stderr, "\tetherswitchcfg [-f control file] reg "
693e6e5db84SAdrian Chadd "register[=value]\n");
694e6e5db84SAdrian Chadd fprintf(stderr, "\tetherswitchcfg [-f control file] vlangroupX "
695e6e5db84SAdrian Chadd "command parameter\n");
696e6e5db84SAdrian Chadd fprintf(stderr, "\t\tvlangroup commands: vlan, members\n");
697270069b7SAdrian Chadd exit(EX_USAGE);
698270069b7SAdrian Chadd }
699270069b7SAdrian Chadd
700270069b7SAdrian Chadd static void
newmode(struct cfg * cfg,enum cmdmode mode)701270069b7SAdrian Chadd newmode(struct cfg *cfg, enum cmdmode mode)
702270069b7SAdrian Chadd {
703270069b7SAdrian Chadd if (mode == cfg->mode)
704270069b7SAdrian Chadd return;
705270069b7SAdrian Chadd switch (cfg->mode) {
706270069b7SAdrian Chadd case MODE_NONE:
707270069b7SAdrian Chadd break;
708e6e5db84SAdrian Chadd case MODE_CONFIG:
709e6e5db84SAdrian Chadd /*
710e6e5db84SAdrian Chadd * Read the updated the configuration (it can be different
711e6e5db84SAdrian Chadd * from the last time we read it).
712e6e5db84SAdrian Chadd */
713e6e5db84SAdrian Chadd if (ioctl(cfg->fd, IOETHERSWITCHGETCONF, &cfg->conf) != 0)
714e6e5db84SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETCONF)");
715e6e5db84SAdrian Chadd print_config(cfg);
716e6e5db84SAdrian Chadd break;
717270069b7SAdrian Chadd case MODE_PORT:
718270069b7SAdrian Chadd print_port(cfg, cfg->unit);
719270069b7SAdrian Chadd break;
720270069b7SAdrian Chadd case MODE_VLANGROUP:
721270069b7SAdrian Chadd print_vlangroup(cfg, cfg->unit);
722270069b7SAdrian Chadd break;
723270069b7SAdrian Chadd case MODE_REGISTER:
724270069b7SAdrian Chadd case MODE_PHYREG:
725138952cfSAdrian Chadd case MODE_ATU:
726270069b7SAdrian Chadd break;
727270069b7SAdrian Chadd }
728270069b7SAdrian Chadd cfg->mode = mode;
729270069b7SAdrian Chadd }
730270069b7SAdrian Chadd
731270069b7SAdrian Chadd int
main(int argc,char * argv[])732270069b7SAdrian Chadd main(int argc, char *argv[])
733270069b7SAdrian Chadd {
734270069b7SAdrian Chadd int ch;
735270069b7SAdrian Chadd struct cfg cfg;
736270069b7SAdrian Chadd int i;
737270069b7SAdrian Chadd
738270069b7SAdrian Chadd bzero(&cfg, sizeof(cfg));
739270069b7SAdrian Chadd cfg.controlfile = "/dev/etherswitch0";
740270069b7SAdrian Chadd while ((ch = getopt(argc, argv, "f:mv?")) != -1)
741270069b7SAdrian Chadd switch(ch) {
742270069b7SAdrian Chadd case 'f':
743270069b7SAdrian Chadd cfg.controlfile = optarg;
744270069b7SAdrian Chadd break;
745270069b7SAdrian Chadd case 'm':
746270069b7SAdrian Chadd cfg.mediatypes++;
747270069b7SAdrian Chadd break;
748270069b7SAdrian Chadd case 'v':
749270069b7SAdrian Chadd cfg.verbose++;
750270069b7SAdrian Chadd break;
751270069b7SAdrian Chadd case '?':
752270069b7SAdrian Chadd /* FALLTHROUGH */
753270069b7SAdrian Chadd default:
754e6e5db84SAdrian Chadd usage(&cfg, argv);
755270069b7SAdrian Chadd }
756270069b7SAdrian Chadd argc -= optind;
757270069b7SAdrian Chadd argv += optind;
758270069b7SAdrian Chadd cfg.fd = open(cfg.controlfile, O_RDONLY);
759270069b7SAdrian Chadd if (cfg.fd < 0)
760270069b7SAdrian Chadd err(EX_UNAVAILABLE, "Can't open control file: %s", cfg.controlfile);
761270069b7SAdrian Chadd if (ioctl(cfg.fd, IOETHERSWITCHGETINFO, &cfg.info) != 0)
762270069b7SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETINFO)");
763e6e5db84SAdrian Chadd if (ioctl(cfg.fd, IOETHERSWITCHGETCONF, &cfg.conf) != 0)
764e6e5db84SAdrian Chadd err(EX_OSERR, "ioctl(IOETHERSWITCHGETCONF)");
765270069b7SAdrian Chadd if (argc == 0) {
766270069b7SAdrian Chadd print_info(&cfg);
767270069b7SAdrian Chadd return (0);
768270069b7SAdrian Chadd }
769270069b7SAdrian Chadd cfg.mode = MODE_NONE;
770270069b7SAdrian Chadd while (argc > 0) {
771270069b7SAdrian Chadd switch(cfg.mode) {
772270069b7SAdrian Chadd case MODE_NONE:
773270069b7SAdrian Chadd if (strcmp(argv[0], "info") == 0) {
774270069b7SAdrian Chadd print_info(&cfg);
775270069b7SAdrian Chadd } else if (sscanf(argv[0], "port%d", &cfg.unit) == 1) {
776270069b7SAdrian Chadd if (cfg.unit < 0 || cfg.unit >= cfg.info.es_nports)
777ba5ff393SHiren Panchasara errx(EX_USAGE, "port unit must be between 0 and %d", cfg.info.es_nports - 1);
778270069b7SAdrian Chadd newmode(&cfg, MODE_PORT);
779270069b7SAdrian Chadd } else if (sscanf(argv[0], "vlangroup%d", &cfg.unit) == 1) {
780270069b7SAdrian Chadd if (cfg.unit < 0 || cfg.unit >= cfg.info.es_nvlangroups)
781da2a0dcbSLuiz Otavio O Souza errx(EX_USAGE,
782da2a0dcbSLuiz Otavio O Souza "vlangroup unit must be between 0 and %d",
783da2a0dcbSLuiz Otavio O Souza cfg.info.es_nvlangroups - 1);
784270069b7SAdrian Chadd newmode(&cfg, MODE_VLANGROUP);
785e6e5db84SAdrian Chadd } else if (strcmp(argv[0], "config") == 0) {
786e6e5db84SAdrian Chadd newmode(&cfg, MODE_CONFIG);
787270069b7SAdrian Chadd } else if (strcmp(argv[0], "phy") == 0) {
788270069b7SAdrian Chadd newmode(&cfg, MODE_PHYREG);
789270069b7SAdrian Chadd } else if (strcmp(argv[0], "reg") == 0) {
790270069b7SAdrian Chadd newmode(&cfg, MODE_REGISTER);
791e6e5db84SAdrian Chadd } else if (strcmp(argv[0], "help") == 0) {
792e6e5db84SAdrian Chadd usage(&cfg, argv);
793138952cfSAdrian Chadd } else if (strcmp(argv[0], "atu") == 0) {
794138952cfSAdrian Chadd newmode(&cfg, MODE_ATU);
795270069b7SAdrian Chadd } else {
796270069b7SAdrian Chadd errx(EX_USAGE, "Unknown command \"%s\"", argv[0]);
797270069b7SAdrian Chadd }
798270069b7SAdrian Chadd break;
799270069b7SAdrian Chadd case MODE_PORT:
800e6e5db84SAdrian Chadd case MODE_CONFIG:
801270069b7SAdrian Chadd case MODE_VLANGROUP:
802138952cfSAdrian Chadd case MODE_ATU:
803270069b7SAdrian Chadd for(i=0; cmds[i].name != NULL; i++) {
804138952cfSAdrian Chadd int r;
805138952cfSAdrian Chadd if (cfg.mode == cmds[i].mode &&
806138952cfSAdrian Chadd strcmp(argv[0], cmds[i].name) == 0) {
807138952cfSAdrian Chadd if ((cmds[i].args != -1) &&
808138952cfSAdrian Chadd (argc < (cmds[i].args + 1))) {
809138952cfSAdrian Chadd printf("%s needs %d argument%s\n",
810138952cfSAdrian Chadd cmds[i].name, cmds[i].args,
811138952cfSAdrian Chadd (cmds[i].args==1)?"":",");
812cdf0868aSAdrian Chadd break;
813cdf0868aSAdrian Chadd }
814138952cfSAdrian Chadd
815138952cfSAdrian Chadd r = (cmds[i].f)(&cfg, argc, argv);
816138952cfSAdrian Chadd
817138952cfSAdrian Chadd /* -1 here means "error" */
818138952cfSAdrian Chadd if (r == -1) {
819138952cfSAdrian Chadd argc = 0;
820138952cfSAdrian Chadd break;
821138952cfSAdrian Chadd }
822138952cfSAdrian Chadd
823138952cfSAdrian Chadd /* Legacy return value */
824138952cfSAdrian Chadd if (r == 0)
825138952cfSAdrian Chadd r = cmds[i].args;
826138952cfSAdrian Chadd
827138952cfSAdrian Chadd argc -= r;
828138952cfSAdrian Chadd argv += r;
829270069b7SAdrian Chadd break;
830270069b7SAdrian Chadd }
831270069b7SAdrian Chadd }
832270069b7SAdrian Chadd if (cmds[i].name == NULL) {
833270069b7SAdrian Chadd newmode(&cfg, MODE_NONE);
834270069b7SAdrian Chadd continue;
835270069b7SAdrian Chadd }
836270069b7SAdrian Chadd break;
837270069b7SAdrian Chadd case MODE_REGISTER:
838270069b7SAdrian Chadd if (set_register(&cfg, argv[0]) != 0) {
839270069b7SAdrian Chadd newmode(&cfg, MODE_NONE);
840270069b7SAdrian Chadd continue;
841270069b7SAdrian Chadd }
842270069b7SAdrian Chadd break;
843270069b7SAdrian Chadd case MODE_PHYREG:
844270069b7SAdrian Chadd if (set_phyregister(&cfg, argv[0]) != 0) {
845270069b7SAdrian Chadd newmode(&cfg, MODE_NONE);
846270069b7SAdrian Chadd continue;
847270069b7SAdrian Chadd }
848270069b7SAdrian Chadd break;
849270069b7SAdrian Chadd }
850270069b7SAdrian Chadd argc--;
851270069b7SAdrian Chadd argv++;
852270069b7SAdrian Chadd }
853270069b7SAdrian Chadd /* switch back to command mode to print configuration for last command */
854270069b7SAdrian Chadd newmode(&cfg, MODE_NONE);
855270069b7SAdrian Chadd close(cfg.fd);
856270069b7SAdrian Chadd return (0);
857270069b7SAdrian Chadd }
858270069b7SAdrian Chadd
859ae824d80SEd Schouten static struct cmds cmds[] = {
860a3219359SAdrian Chadd { MODE_PORT, "pvid", 1, set_port_vid },
861270069b7SAdrian Chadd { MODE_PORT, "media", 1, set_port_media },
862270069b7SAdrian Chadd { MODE_PORT, "mediaopt", 1, set_port_mediaopt },
8631cec2c73SAdrian Chadd { MODE_PORT, "led", 2, set_port_led },
864e6e5db84SAdrian Chadd { MODE_PORT, "addtag", 0, set_port_flag },
865e6e5db84SAdrian Chadd { MODE_PORT, "-addtag", 0, set_port_flag },
866e6e5db84SAdrian Chadd { MODE_PORT, "ingress", 0, set_port_flag },
867e6e5db84SAdrian Chadd { MODE_PORT, "-ingress", 0, set_port_flag },
868e6e5db84SAdrian Chadd { MODE_PORT, "striptag", 0, set_port_flag },
869e6e5db84SAdrian Chadd { MODE_PORT, "-striptag", 0, set_port_flag },
870f5b29d0fSKornel Duleba { MODE_PORT, "striptagingress", 0, set_port_flag },
871f5b29d0fSKornel Duleba { MODE_PORT, "-striptagingress", 0, set_port_flag },
872e6e5db84SAdrian Chadd { MODE_PORT, "doubletag", 0, set_port_flag },
873e6e5db84SAdrian Chadd { MODE_PORT, "-doubletag", 0, set_port_flag },
874e6e5db84SAdrian Chadd { MODE_PORT, "firstlock", 0, set_port_flag },
875e6e5db84SAdrian Chadd { MODE_PORT, "-firstlock", 0, set_port_flag },
8764e4cedb0SLuiz Otavio O Souza { MODE_PORT, "droptagged", 0, set_port_flag },
8774e4cedb0SLuiz Otavio O Souza { MODE_PORT, "-droptagged", 0, set_port_flag },
878e6e5db84SAdrian Chadd { MODE_PORT, "dropuntagged", 0, set_port_flag },
879e6e5db84SAdrian Chadd { MODE_PORT, "-dropuntagged", 0, set_port_flag },
880e6e5db84SAdrian Chadd { MODE_CONFIG, "vlan_mode", 1, set_vlan_mode },
881270069b7SAdrian Chadd { MODE_VLANGROUP, "vlan", 1, set_vlangroup_vid },
882270069b7SAdrian Chadd { MODE_VLANGROUP, "members", 1, set_vlangroup_members },
883138952cfSAdrian Chadd { MODE_ATU, "flush", -1, atu_flush },
884138952cfSAdrian Chadd { MODE_ATU, "dump", -1, atu_dump },
885270069b7SAdrian Chadd { 0, NULL, 0, NULL }
886270069b7SAdrian Chadd };
887