1/*
2 * IEEE 802.1Q Virtual LAN services
3 *
4 * Copyright 2004, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id: vlan.c,v 1.1.1.1 2008/10/15 03:28:48 james26_jang Exp $
13 */
14#ifdef WL500GX
15#include <stdio.h>
16#include <stdlib.h>
17#include <errno.h>
18#include <syslog.h>
19#include <ctype.h>
20#include <string.h>
21#include <unistd.h>
22#include <sys/stat.h>
23#include <sys/ioctl.h>
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <net/if.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
29#include <net/if_arp.h>
30#include <bcmnvram.h>
31#include <netconf.h>
32#include <shutils.h>
33#include <rc.h>
34#include <errno.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include <fcntl.h>
39#include <strings.h>
40#include <sys/ioctl.h>
41#include <../../linux/linux/include/linux/if_vlan.h>
42#include <linux/sockios.h>
43#include <string.h>
44#include <sys/socket.h>
45#include <sys/types.h>
46#define uint32 unsigned long
47#define uint unsigned int
48#define uint8 unsigned char
49#define uint64 unsigned long long
50#include <swmod.h>
51#include <swapi.h>
52#include <nvports.h>
53#include <bcmdevs.h>
54#include <nvparse.h>
55extern int wan_valid(char *ifname);
56
57
58/* VLAN Descriptors, per-board or platform setting */
59struct vlan_board_s{
60    char* bd_name;
61    char* bd_desc;
62    int numports;
63    int wan_port;
64    int lan_port_start;
65    int lan_port_end;
66    int vlan_devno;
67	int wan_vlan;
68	int lan_vlan;
69} vlan_boards[] = {
70    {"reference board",
71    "Broadcom Sentry5",
72    BCM_NUM_PORTS,
73    BCM_WAN_PORT,
74    BCM_LAN_MIN_PORT,
75    BCM_LAN_MAX_PORT,
76    0,
77	BCM_DEF_WAN_VLAN,
78	BCM_DEF_LAN_VLAN},
79};
80int vlan_configured = 0;
81int brcm_tag_driver_enabled = 0;
82#define IFUP (IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST)
83
84
85static void
86enable_wan_port(void)
87{
88	char val8 = 0;
89
90	if ((bcm_api_init()) < 0)
91		return;
92
93	/* enable physical WAN port */
94	bcm_write_reg(0, ROBO_CTRL_PAGE, ROBO_PORT0_CTRL, &val8, 1);
95
96	bcm_api_deinit();
97}
98
99static int
100vlan_configure(void)
101
102{
103
104    char *vlan_enable = nvram_safe_get("vlan_enable");
105    char *lan_ifname = nvram_safe_get("lan_ifname");
106    char *lan_ifnames = nvram_safe_get("lan_ifnames");
107    char *wan_hwaddr = nvram_safe_get("wan0_hwaddr"); //Thanks for Oleg
108    char *wan_ifname = NULL;
109	char *wan_proto;
110	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
111    char *restore_lan_ifname = nvram_safe_get("restore_lan_ifname");
112    char *restore_lan_ifnames = nvram_safe_get("restore_lan_ifnames");
113    char *restore_wan_ifname = nvram_safe_get("restore_wan_ifname");
114    char *restore_wan_hwaddr = nvram_safe_get("restore_wan_hwaddr");
115    char *mibac_enable = nvram_safe_get("mibac_enable");
116    char *mibac_interval = nvram_safe_get("mibac_interval");
117    char *brcmtag_enable = nvram_safe_get("brcmtag_enable");
118    char *wan_vlan = nvram_safe_get("wan_vlan");
119    char *lan_vlan = nvram_safe_get("lan_vlan");
120    char *lan_br_name;
121    char buf[80];
122    char lan_ifbase_realdev[80], wan_ifbase[80];
123    char name[80], lan_ifbase[80], br_group[80], *next, vlan[4], vlan_wan[4], port[4];
124    uint bVlan, board_index = 0, i, buf_index = 0, hasBridge = 0;
125    uint bBrcmTag, bMIBAC;
126    uint wan_vid = 0, lan_vid = 0, lan_vids[BCM_NUM_PORTS-1], vid;
127	int unit;
128
129    bcm_l2_addr_t l2addr;
130    bcm_mac_t eth_addr, mcast_addr = BRIDGE_GROUP_MAC_ADDR;
131    int retval;
132    unsigned short MIBport;
133    bcm_mac_t MIBda;
134    uint mibac_int = ROBO_AC_RATE_DEFAULT;
135
136    if (!bcm_is_robo())
137      return -1;
138    bVlan = (atoi(vlan_enable) > 0) ||(strlen(vlan_enable) &&
139	     !strncmp(vlan_enable,"true", strlen(vlan_enable)));
140    printf("\n\nBroadcom Enterprise RG/AP\n");
141    printf("\r\nBroadcom ROBO 802.1Q VLAN %s\n",
142	   bVlan > 0 ? "enabled" :"disabled");
143
144    bMIBAC = (atoi(mibac_enable) > 0) ||
145	    (strlen(mibac_enable) &&
146	     !strncmp(mibac_enable,"true", strlen(mibac_enable)));
147
148    bBrcmTag = ((atoi(brcmtag_enable) > 0) ||
149	    (strlen(brcmtag_enable) &&
150	     !strncmp(brcmtag_enable,"true", strlen(brcmtag_enable))));
151
152    if (strlen(mibac_interval))
153    {
154        mibac_int = ROBO_GET_AC_RATE(atoi(mibac_interval));
155        if (mibac_int > ROBO_AC_RATE_MAX)
156            mibac_int = ROBO_AC_RATE_MAX;
157    }
158
159	/* find configured and enabled WAN connection */
160	for (unit = 0; unit < MAX_NVPARSE; unit ++) {
161		snprintf(prefix, sizeof(prefix), "wan%d_", unit);
162    	wan_ifname = nvram_get(strcat_r(prefix, "ifname", tmp));
163    	if (!wan_ifname)
164    		continue;
165    	wan_proto = nvram_get(strcat_r(prefix, "proto", tmp));
166    	if (!wan_proto || !strcmp(wan_proto, "disabled"))
167    		continue;
168		/* disable the connection if the i/f is not in wan_ifnames */
169		if (!wan_valid(wan_ifname)) {
170			nvram_set(strcat_r(prefix, "proto", tmp), "disabled");
171			continue;
172        }
173        break;
174    }
175
176	if (!wan_ifname)
177    {
178        if (bcm_is_robo())
179        {
180        	dprintf("No active, configured WAN interface found\n");
181		enable_wan_port();
182        }
183        return -1;
184    }
185
186    /* check to make sure vlan numbers are valid */
187    /* (if no nvram variables, use defaults) */
188    if (strlen(wan_vlan))
189        wan_vid = atoi(wan_vlan);
190    else
191        wan_vid = vlan_boards[board_index].wan_vlan;
192    if (strlen(lan_vlan))
193        lan_vid = atoi(lan_vlan);
194    else
195        lan_vid = vlan_boards[board_index].lan_vlan;
196    for (i=0;i<BCM_NUM_PORTS;i++)
197        lan_vids[i] = 0;
198    if (wan_vid == 0 || wan_vid > VLAN_ID_MAX)
199    {
200    	printf("'wan_vlan' does not have valid vlan id\n");
201    	bVlan = 0;
202    }
203    if (lan_vid == 0 || lan_vid > VLAN_ID_MAX || lan_vid == wan_vid)
204    {
205    	printf("'lan_vlan' does not have valid vlan id\n");
206    	bVlan = 0;
207    }
208
209    /* first restore ifnames, if necessary.  note that if the user */
210    /* wants to change lan_ifname or wan_ifname, it will be necessary */
211    /* to delete the corresponding 'restore' value to avoid subsequent */
212    /* overwriting of the new value when the router starts */
213    if (strlen(restore_wan_ifname)) {
214	if (nvram_set(strcat_r(prefix, "ifname", tmp), restore_wan_ifname))
215	    return -1;
216	if (nvram_unset("restore_wan_ifname"))
217	    return -1;
218    }
219    if (strlen(restore_lan_ifname)) {
220	if (nvram_set("lan_ifname", restore_lan_ifname))
221	    return -1;
222	if (nvram_unset("restore_lan_ifname"))
223	    return -1;
224    }
225    if (strlen(restore_lan_ifnames)) {
226	if (nvram_set("lan_ifnames", restore_lan_ifnames))
227	    return -1;
228	if (nvram_unset("restore_lan_ifnames"))
229	    return -1;
230    }
231    if (strlen(restore_wan_hwaddr)) {
232	if (nvram_set(strcat_r(prefix, "hwaddr", tmp), restore_wan_hwaddr))
233	    return -1;
234	if (nvram_unset("restore_wan_hwaddr"))
235	    return -1;
236    }
237
238    /* now check to see if vlan disabled */
239    /* disabled, just exit */
240    if (!bVlan)
241    {
242	enable_wan_port();
243	return 0;
244    }
245
246    /* activate interface to Robo switch */
247    if ((bcm_api_init())<0) {
248        if (bcm_is_robo())
249        {
250        	dprintf("No ROBO device found\n");
251        }
252        return -1;
253    }
254    /* create interface names */
255    /* get base name that interface will be based on */
256    sprintf(lan_ifbase,"eth%d",vlan_boards[board_index].vlan_devno);
257
258    /* check to see if bridge has been set up */
259    if (strncmp(lan_ifname, "br", 2) == 0) {
260    	/* iterate though members of bridge group and extract lan name for */
261    	/* use in creating vlans and create list w/o lan member, which will */
262    	/* have vlan group members added below */
263    	buf_index = 0;
264    	foreach(name, nvram_safe_get("lan_ifnames"), next) {
265    	    if (strncmp(name, lan_ifbase, 4) == 0) {
266    		hasBridge = 1;
267    	    }
268    	    else {
269    		strcpy(&br_group[buf_index],name);
270    		strcat(br_group," ");
271    		buf_index = strlen(br_group);
272    	    }
273    	}
274    }
275
276    /* note that if brcm tags are enabled, the WAN is configured with a vlan and */
277    /* the LAN ports are configured with the brcm tag driver.  if brcm tags are disabled */
278    /* the LAN is configured with a vlan and the WAN directly uses eth0.  This */
279    /* only applies to vlan interfaces created with vconfig.  In both cases, the underlying */
280    /* switch is programmed with a separate vlan for WAN and LAN, but in the case w/o */
281    /* brcm tags, the WAN vlan tag is removed when it exits the switch to the CPU */
282
283    /* modify lan_ifbase & wan_ifbase for brcm tag driver, but save to bring up interface */
284    strcpy(lan_ifbase_realdev,lan_ifbase);
285	strcpy(wan_ifbase,lan_ifbase);
286    if (bBrcmTag)
287	{
288        /* if brcm tag driver will be used, add 't' to root name */
289        strcat(lan_ifbase,"t");
290        strcat(wan_ifbase,"t");
291		sprintf(buf,".%d",vlan_boards[board_index].wan_port);
292		strcat(wan_ifbase,buf);
293        /* need to create wan vlan name here.  the form of the name will be ethx.port.vlan */
294        sprintf(buf,"%s.%d",wan_ifbase,wan_vid);
295        nvram_set("restore_wan_ifname",wan_ifname);
296        nvram_set(strcat_r(prefix, "ifname", tmp),buf);
297        nvram_set(strcat_r(prefix, "ifnames", tmp),buf);
298	}
299
300	/* we need to handle the case of if bridge exists or not.  if
301	 * it does exist, and brcm tags are enabled brcm tag (for default) interface names will be
302     * substituted for 'ethx' name.  if it doesn't exist, bridge 'br0' will be created
303	 * with only vlan or brcm tag interface names
304	 */
305	if (hasBridge) {
306	    lan_br_name = lan_ifname;
307	    strcpy(&buf[0],&br_group[0]);
308	} else {
309	    lan_br_name = "br0";
310	    buf_index = 0;
311	    hasBridge = 1;
312	}
313	for (i = vlan_boards[board_index].lan_port_start;
314	     i <= vlan_boards[board_index].lan_port_end;i++) {
315        if (bBrcmTag)
316            /* use port ids for interface suffixes */
317	        sprintf(&buf[buf_index],"%s.%d ",lan_ifbase,i);
318        else
319            /* use single lan vlan id interface suffixes */
320	        sprintf(&buf[buf_index],"%s.%d ",lan_ifbase,lan_vid);
321	    buf_index = strlen(buf);
322        if (!bBrcmTag)
323            /* if no brcm tag driver, just use one interface for all ports on LAN side */
324            break;
325	}
326	/* get rid of last space */
327	buf[strlen(buf) - 1] = '\0';
328    printf("lan_ifnames %s\n",buf);
329	nvram_set("restore_lan_ifnames",lan_ifnames);
330	nvram_set("restore_lan_ifname",lan_ifname);
331	nvram_set("lan_ifnames",buf);
332	nvram_set("lan_ifname",lan_br_name);
333
334    /* change wan_hwaddr to be lan_hwaddr.  this is because underlying
335     * lan device has lan_hwaddr and if wan vlan device had different
336     * hwaddr, the vlan processing would set the underlying device to
337     * promiscuous mode
338     */
339    nvram_set("restore_wan_hwaddr",wan_hwaddr);
340    nvram_set(strcat_r(prefix, "hwaddr", tmp),nvram_safe_get("lan_hwaddr"));
341
342    /* now create vlan i/f's */
343    /* need to bring up the underlying switch i/f to create vlans */
344    ifconfig(lan_ifbase_realdev, IFUP, 0, 0);
345
346    if (bBrcmTag)
347    {
348		/* create brcm tag device for wan */
349        bcm_reg_brcmtag_dev(lan_ifbase_realdev, "t", vlan_boards[board_index].wan_port);
350        ifconfig(wan_ifbase, IFUP, 0, 0);
351    }
352
353    /* first, wan vlan.  note, must also configure wan here, in case */
354    /* it's the same wan being used for nfs, in order to allow nfs to */
355    /* keep working during configuration of vlans */
356    sprintf(vlan_wan,"%d",wan_vid);
357    eval("vconfig","set_name_type","DEV_PLUS_VID_NO_PAD");
358    if (bBrcmTag)
359        eval("vconfig","add",wan_ifbase,vlan_wan);
360    else
361        /* don't configure WAN as vlan interface, just program switch with vlan id */
362        bcm_vlan_create(0,wan_vid); /* this is for default case, which doesn't call vconfig */
363    /* Bring up WAN interface */
364    ifconfig(nvram_safe_get(strcat_r(prefix, "ifname", tmp)), IFUP,
365        nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)),
366        nvram_safe_get(strcat_r(prefix, "netmask", tmp)));
367    /* now configure wan vlan and enable vlans */
368    sprintf(port,"%d",vlan_boards[board_index].wan_port);
369    eval("vconfig","add_port",vlan_wan,port);
370    /* MII port is set up to tag with wan vlan here, but that will be overridden below */
371    /* to tag with lan vlan (only matters for default case where CPU doesn't have vlan */
372    /* configured, but switch does; ie, mii port does tag/untag) */
373    sprintf(port,"%d",BCM_MII_PORT); /* mii port, note that vlan tags retained on egress */
374    if (bBrcmTag)
375        eval("vconfig","add_port_nountag",vlan_wan,port);
376    else
377        /* if no BRCM tags, untag MII for WAN VLAN */
378        eval("vconfig","add_port",vlan_wan,port);
379    if (bBrcmTag)
380        /* set flag to let vlan dev build headers in vlan_dev_hard_header */
381        eval("vconfig","set_flag",nvram_safe_get(strcat_r(prefix, "wan_ifname", tmp)),"1","0");
382
383    /* now enable switch ports for vlan */
384    sprintf(buf,"%d",1);
385    eval("vconfig","ports_enable",buf);
386
387    /* set multicast related registers */
388    buf[0] = 0x0a;      /* Rsvd MC tag/untag */
389	if (bBrcmTag)
390		/* if default mode, allow tagging of frames into MII.  this is to allow */
391		/* lan to have vlan handling in switch, but remove vlan tag when received */
392		/* by CPU */
393		buf[0] |= 0x80;
394    bcm_write_reg(0,ROBO_VLAN_PAGE,ROBO_VLAN_CTRL1,buf,1);
395    buf[0] = 0x01;      /* enable MC ARL entries to use port map  */
396    bcm_write_reg(0,ROBO_CTRL_PAGE,ROBO_IP_MULTICAST_CTRL,buf,1);
397    buf[0] = 0x1c;      /* MII receive unicast, multicast, broadcast */
398    bcm_write_reg(0,ROBO_CTRL_PAGE,ROBO_IM_PORT_CTRL,buf,1);
399    buf[0] = 0x40;      /* drop frame if frame has VID violation */
400    bcm_write_reg(0,ROBO_VLAN_PAGE,ROBO_VLAN_CTRL4,buf,1);
401    buf[0] = 0x08;      /* drop frame if vtable miss */
402    bcm_write_reg(0,ROBO_VLAN_PAGE,ROBO_VLAN_CTRL5,buf,1);
403    if (bBrcmTag)
404    {
405        /* now set up managed mode registers for brcm tag */
406        buf[0] = 0x00;      /* Rsvd MC tag/untag */
407        bcm_write_reg(0,ROBO_VLAN_PAGE,ROBO_VLAN_CTRL1,buf,1);
408        buf[0] = 0x8e;      /* MII port as management port, IGMP snoop, rx BPDUs */
409        bcm_write_reg(0,ROBO_MGMT_PAGE,ROBO_GLOBAL_CONFIG,buf,1);
410        buf[0] = 0x08;      /* mgmt port ID */
411        bcm_write_reg(0,ROBO_MGMT_PAGE,ROBO_MGMT_PORT_ID,buf,1);
412        buf[0] = 0x0a;      /* ignore crc check on mgmt port */
413        bcm_write_reg(0,ROBO_VLAN_PAGE,ROBO_VLAN_CTRL5,buf,1);
414        buf[0] = 0x03;      /* turn on managed mode */
415        bcm_write_reg(0,ROBO_CTRL_PAGE,ROBO_SWITCH_MODE,buf,1);
416        brcm_tag_driver_enabled = 1;
417    }
418    /* now assign 0.0.0.0 ip address to i/f underlying vlans */
419	if (bBrcmTag)
420        ifconfig(lan_ifbase_realdev, IFUP, "0.0.0.0", "0.0.0.0");
421
422    /* now lan vlan */
423    for (i = vlan_boards[board_index].lan_port_start;
424         i <= vlan_boards[board_index].lan_port_end;i++) {
425        /* if default, no vconfig, because */
426		/* vlan untagged at MII port */
427        if (bBrcmTag) {
428			/* default mode (w/brcm tags), create brcm tag device per port and set up */
429            /* single vlan for all ports */
430			if (i == vlan_boards[board_index].lan_port_start)
431			{
432                bcm_vlan_create(0,lan_vid); /* this is for default case, which doesn't call vconfig */
433				sprintf(vlan,"%d",lan_vid);
434				sprintf(port,"%d",BCM_MII_PORT); /* mii port */
435				eval("vconfig","add_port",vlan,port);
436			}
437  			sprintf(port,"%d",i);
438  			eval("vconfig","add_port",vlan,port);
439			bcm_reg_brcmtag_dev(lan_ifbase_realdev, "t", i);
440        } else {
441            /* brcm tags disabled.  create one vlan interface for LAN */
442            if (i == vlan_boards[board_index].lan_port_start)
443            {
444                /* only create one vlan for default mode w/no brcm tags */
445                sprintf(vlan,"%d",lan_vid);
446    			eval("vconfig","add",lan_ifbase,vlan);
447    			/* also add mii port */
448    			sprintf(port,"%d",BCM_MII_PORT); /* mii port */
449    			eval("vconfig","add_port_nountag_nodeftag",vlan,port);
450            }
451			sprintf(port,"%d",i);
452			eval("vconfig","add_port",vlan,port);
453            /* add interface to port/interface map */
454            bcm_add_port_interface(i, lan_vid);
455		}
456    }
457
458    if (hasBridge && bBrcmTag)
459    {
460      /* init spanning tree state */
461      /* set WAN port & MII to forwarding, all others to disabled */
462      bcm_port_stp_set(BCM_WAN_PORT,BCM_PORT_STP_FORWARD);
463      bcm_port_stp_set(9,BCM_PORT_STP_FORWARD);
464      for (i = vlan_boards[board_index].lan_port_start;
465           i <= vlan_boards[board_index].lan_port_end;i++)
466        bcm_port_stp_set(i,BCM_PORT_STP_DISABLE);
467    } else {
468      /* init spanning tree state to none for all ports */
469      for (i=1;i<=BCM_MAX_PORT;i++)
470        bcm_port_stp_set(i,BCM_PORT_STP_NONE);
471    }
472    /* add static entries to arl for wan hwaddr & lan hwaddr */
473    ether_atoe(nvram_safe_get(strcat_r(prefix, "hwaddr", tmp)), eth_addr);
474    bcm_l2_addr_init(&l2addr,eth_addr,wan_vid);
475    l2addr.port = BCM_MII_ARL_UC_PORT-1;
476    if (BCM_RET_SUCCESS != (retval = bcm_l2_addr_add(0, &l2addr)))
477      dprintf("failure writing wan l2 addr: %d\n",retval);
478    ether_atoe(nvram_safe_get("lan_hwaddr"), eth_addr);
479    /* set up MIB autocast, if enabled */
480    if (bMIBAC)
481    {
482        /* set up MIB AC (dst, src, port & rate) */
483        memcpy(MIBda,eth_addr,sizeof(bcm_mac_t));
484        bcm_byteswap(&MIBda);
485        bcm_write_reg(0,ROBO_MIB_AC_PAGE,ROBO_MIB_AC_DA,MIBda,sizeof(bcm_mac_t));
486        memset(buf,0,sizeof(bcm_mac_t));
487        bcm_write_reg(0,ROBO_MIB_AC_PAGE,ROBO_MIB_AC_SA,buf,sizeof(bcm_mac_t));
488        MIBport = PBMP_PORT(BCM_MII_ARL_UC_PORT-1);
489        bcm_write_reg(0,ROBO_MIB_AC_PAGE,ROBO_MIB_AC_PORT,(uint8 *)&MIBport,sizeof(MIBport));
490        bcm_write_reg(0,ROBO_MIB_AC_PAGE,ROBO_MIB_AC_RATE,(uint8 *)&mibac_int,sizeof(char));
491        bcm_read_reg(0,ROBO_MGMT_PAGE,ROBO_GLOBAL_CONFIG,buf,1);
492        buf[0] |= 0x20;      /* enable MIB AC */
493        bcm_write_reg(0,ROBO_MGMT_PAGE,ROBO_GLOBAL_CONFIG,buf,1);
494    }
495    /* now multicast entry for BPDUs */
496    bcm_l2_addr_init(&l2addr,mcast_addr,wan_vid);
497    l2addr.pbmp = PBMP_PORT(i-1) | PBMP_PORT(BCM_MII_PORT-1);
498    if (BCM_RET_SUCCESS != (retval = bcm_l2_addr_add(0, &l2addr)))
499      dprintf("failure writing lan l2 addr: %d\n",retval);
500    for (i = vlan_boards[board_index].lan_port_start;
501         i <= vlan_boards[board_index].lan_port_end;i++) {
502      vid = lan_vid;
503      if (i == vlan_boards[board_index].lan_port_start) {
504        bcm_l2_addr_init(&l2addr,eth_addr,vid);
505        l2addr.port = BCM_MII_ARL_UC_PORT-1;
506        if (BCM_RET_SUCCESS != (retval = bcm_l2_addr_add(0, &l2addr)))
507          dprintf("failure writing lan l2 addr: %d\n",retval);
508        /* now multicast entry for BPDUs */
509        bcm_l2_addr_init(&l2addr,mcast_addr,vid);
510        l2addr.pbmp = PBMP_PORT(i-1) | PBMP_PORT(BCM_MII_PORT-1);
511        if (BCM_RET_SUCCESS != (retval = bcm_l2_addr_add(0, &l2addr)))
512          dprintf("failure writing lan l2 addr: %d\n",retval);
513      }
514    }
515    if (!bBrcmTag)
516    {
517        /* if in mgmt mode (if brcm tag driver used), don't need to do this */
518        /* set bogus mc addr to bypass specian h/w handling of BPDUs and let ARL handle them */
519        memset(&mcast_addr,0,sizeof(mcast_addr));
520        bcm_write_reg(0,ROBO_ARLCTRL_PAGE,ROBO_BPDU_MC_ADDR_REG,mcast_addr,sizeof(mcast_addr));
521    }
522    vlan_configured = 1;
523    /* deinit Robo switch interface */
524    bcm_api_deinit();
525
526    /* We had changed wan_hwaddr to be the same as lan_hwaddr (temporarily)
527       due the issue of promiscuous.
528       Now it's time to roll it back. */
529    restore_wan_hwaddr = nvram_safe_get("restore_wan_hwaddr");
530    if (strlen(restore_wan_hwaddr))
531    {
532    	if (nvram_set(strcat_r(prefix, "hwaddr", tmp), restore_wan_hwaddr))
533	    return -1;
534	if (nvram_unset("restore_wan_hwaddr"))
535	    return -1;
536    }
537
538    nvram_commit();
539
540  return 0;
541}
542
543static int
544vlan_deconfigure(void)
545{
546    char *restore_lan_ifname = nvram_safe_get("restore_lan_ifname");
547    char *restore_lan_ifnames = nvram_safe_get("restore_lan_ifnames");
548    char *restore_wan_ifname = nvram_safe_get("restore_wan_ifname");
549    char *restore_wan_hwaddr = nvram_safe_get("restore_wan_hwaddr");
550    char *wan_ifname = NULL;
551	char *wan_proto;
552	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
553    char buf[80];
554    char name[80], *next;
555    uint  board_index = 0;
556	int unit;
557
558    /* first, bring down vlans, if enabled */
559    dprintf("deconfigure vlan\n");
560    if (vlan_configured) {
561
562    /* activate interface to Robo switch */
563    if ((bcm_api_init())<0) {
564	    dprintf("No ROBO device found\n");
565	    return -1;
566    }
567
568	/* find configured and enabled WAN connection */
569	for (unit = 0; unit < MAX_NVPARSE; unit ++) {
570		snprintf(prefix, sizeof(prefix), "wan%d_", unit);
571    	wan_ifname = nvram_get(strcat_r(prefix, "ifname", tmp));
572    	if (!wan_ifname)
573    		continue;
574    	wan_proto = nvram_get(strcat_r(prefix, "proto", tmp));
575    	if (!wan_proto || !strcmp(wan_proto, "disabled"))
576    		continue;
577		/* disable the connection if the i/f is not in wan_ifnames */
578		if (!wan_valid(wan_ifname)) {
579			nvram_set(strcat_r(prefix, "proto", tmp), "disabled");
580			continue;
581        }
582    }
583
584	if (!wan_ifname)
585    {
586        if (bcm_is_robo())
587        {
588        	dprintf("No active, configured WAN interface found\n");
589        }
590        return -1;
591    }
592
593	/* vlan is non-zero, that means that eth0 is wan port */
594	if (vlan_boards[board_index].vlan_devno)
595	      ifconfig("eth0", IFUP, nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)),
596          nvram_safe_get(strcat_r(prefix, "netmask", tmp)));
597
598    /* now bring down brcm tag device for wan device */
599    if (brcm_tag_driver_enabled)
600    {
601		/* Strip off vlan suffix */
602        strcpy(name,wan_ifname);
603        next = strrchr(name,'.');
604        if (next != NULL)
605        {
606            *next = '\0';
607            bcm_unreg_brcmtag_dev(name);
608        }
609        buf[0] = 0x02;      /* turn off managed mode */
610        bcm_write_reg(0,ROBO_CTRL_PAGE,ROBO_SWITCH_MODE,buf,1);
611        buf[0] = 0x00;      /* turn off vlan mode */
612        bcm_write_reg(0,ROBO_VLAN_PAGE,ROBO_VLAN_CTRL0,buf,1);
613        /* now, deconfigure wan vlan */
614    	eval("vconfig","rem",wan_ifname);
615    }
616
617	/* now lan vlan */
618	if (brcm_tag_driver_enabled) {
619	    /* default mode, just bring down brcm tag devices per port */
620	    foreach(name, nvram_safe_get("lan_ifnames"), next) {
621    		/* check to see if has suffix  '.port' before removing */
622    		if (strrchr(name,'.') != NULL)
623    		    bcm_unreg_brcmtag_dev(name);
624    	}
625        brcm_tag_driver_enabled = 0;
626    } else
627        /* no brcm tags, bring down lan vlan */
628	    foreach(name, nvram_safe_get("lan_ifnames"), next) {
629    		/* check to see if has suffix  '.port' before removing */
630    		if (strrchr(name,'.') != NULL)
631    	        eval("vconfig","rem",name);
632    	}
633    }
634       /* now disable switch ports for vlan */
635   	sprintf(buf,"%d\n",0);
636   	eval("vconfig","ports_enable",buf);
637    vlan_configured = 0;
638    bcm_api_deinit();
639
640    /* now restore environment */
641    if (strlen(restore_wan_ifname)) {
642	if (nvram_set(strcat_r(prefix, "ifname", tmp), restore_wan_ifname))
643	    return -1;
644	if (nvram_unset("restore_wan_ifname"))
645	    return -1;
646    }
647    if (strlen(restore_lan_ifname)) {
648	if (nvram_set("lan_ifname", restore_lan_ifname))
649	    return -1;
650	if (nvram_unset("restore_lan_ifname"))
651	    return -1;
652    }
653    if (strlen(restore_lan_ifnames)) {
654	if (nvram_set("lan_ifnames", restore_lan_ifnames))
655	    return -1;
656	if (nvram_unset("restore_lan_ifnames"))
657	    return -1;
658    }
659    if (strlen(restore_wan_hwaddr)) {
660	if (nvram_set(strcat_r(prefix, "wan_hwaddr", tmp), restore_wan_hwaddr))
661	    return -1;
662	if (nvram_unset("restore_wan_hwaddr"))
663	    return -1;
664    }
665
666    return 0;
667}
668
669
670/*
671 * Setup VLAN interfaces, if enabled
672 */
673int
674start_vlan(void)
675{
676    /* Bringup vlan interfaces */
677    vlan_configure();
678    return 0;
679}
680
681/*
682 * Stop VLANs, if they have been created.
683 */
684int
685stop_vlan(void)
686{
687
688    /* Shut down vifs */
689    vlan_deconfigure();
690    return 0;
691}
692
693
694int start_portmon()
695{
696
697    /* Start Linkscan */
698    return 0;
699
700}
701
702
703int stop_portmon()
704{
705
706    /* Stop linkscan */
707    return 0;
708}
709#endif
710