1 /* Copyright 2005 Renzo Davoli VDE-2
2 * Some minor remain from uml_switch Copyright 2002 Yon Uriarte and Jeff Dike
3 * Licensed under the GPLv2
13 #include <sys/socket.h>
16 #include <netinet/in.h> /*ntoh conversion*/
34 // for dedugging if needed
37 void packet_dump (struct packet *p)
40 printf ("packet dump dst");
41 for (i=0;i<ETH_ALEN;i++)
42 printf(":%02x",p->header.dest[i]);
44 for (i=0;i<ETH_ALEN;i++)
45 printf(":%02x",p->header.src[i]);
48 printf(":%02x",p->header.proto[i]);
57 struct endpoint
*next
;
60 #define NOTINPOOL 0x8000
66 /* sender is already inside ep, but it needs one more memaccess */
67 int (*sender
)(int fd
, int fd_ctl
, void *packet
, int len
, void *data
, int port
);
68 struct mod_support
*ms
;
76 * table the vlan table (also for inactive ports)
77 * vlan bctag is the vlan table -- only tagged forwarding ports mapping
78 * vlan bcuntag is the vlan table -- only untagged forwarding ports mapping
79 * validvlan is the table of valid vlans
90 #define IS_BROADCAST(addr) ((addr[0] & 1) == 1)
92 static struct port
**portv
;
94 static int alloc_port(unsigned int portno
)
99 for (i
=1;i
<numports
&& portv
[i
] != NULL
&&
100 (portv
[i
]->ep
!= NULL
|| portv
[i
]->flag
& NOTINPOOL
) ;i
++)
102 } else if (i
<0) /* special case MGMT client port */
107 if (portv
[i
] == NULL
) {
109 if ((port
= malloc(sizeof(struct port
))) == NULL
){
110 printlog(LOG_WARNING
,"malloc port %s",strerror(errno
));
118 port
->cost
=DEFAULT_COST
;
123 BA_SET(vlant
[0].table
,i
);
130 static void free_port(unsigned int portno
)
132 if (portno
< numports
) {
133 struct port
*port
=portv
[portno
];
134 if (port
!= NULL
&& port
->ep
==NULL
) {
137 /* delete completely the port. all vlan defs zapped */
138 BAC_FORALL(validvlan
,NUMOFVLAN
,BA_CLR(vlant
[i
].table
,portno
),i
);
144 /* initialize a port structure with control=fd, given data+data_len and sender
146 * and then add it to the g_fdsdata array at index i. */
147 int setup_ep(int portno
, int fd_ctl
,
149 struct mod_support
*modfun
)
154 if ((portno
= alloc_port(portno
)) >= 0) {
156 if (port
->fd_data
< 0)
157 port
->fd_data
=modfun
->newport(fd_ctl
,portno
);
158 if (port
->fd_data
>= 0 &&
159 (ep
=malloc(sizeof(struct endpoint
))) != NULL
) {
161 port
->sender
=modfun
->sender
;
166 if(port
->ep
== NULL
) {/* WAS INACTIVE */
168 /* copy all the vlan defs to the active vlan defs*/
171 BAC_FORALL(validvlan
,NUMOFVLAN
,
172 ({if (BA_CHECK(vlant
[i
].table
,portno
)) {
173 BA_SET(vlant
[i
].bctag
,portno
);
175 fstaddport(i
,portno
,(i
!=port
->vlanuntag
));
179 if (port
->vlanuntag
!= NOVLAN
) {
180 BA_SET(vlant
[port
->vlanuntag
].bcuntag
,portno
);
181 BA_CLR(vlant
[port
->vlanuntag
].bctag
,portno
);
183 BA_CLR(vlant
[port
->vlanuntag
].notlearning
,portno
);
199 void setup_description(int portno
, int fd_ctl
, char *descr
)
201 if (portno
>=0 && portno
< numports
) {
202 struct port
*port
=portv
[portno
];
205 for (ep
=port
->ep
;ep
!=NULL
;ep
=ep
->next
)
206 if (ep
->fd_ctl
== fd_ctl
)
213 static int rec_close_ep(struct endpoint
**pep
, int fd_ctl
)
215 struct endpoint
*this=*pep
;
217 if (this->fd_ctl
==fd_ctl
) {
219 if (portv
[this->port
]->ms
->delep
)
220 portv
[this->port
]->ms
->delep(this->fd_ctl
,this->data
,this->descr
);
224 return rec_close_ep(&(this->next
),fd_ctl
);
229 int close_ep(int portno
, int fd_ctl
)
231 if (portno
>=0 && portno
< numports
) {
232 struct port
*port
=portv
[portno
];
234 int rv
=rec_close_ep(&(port
->ep
),fd_ctl
);
235 if (port
->ep
== NULL
) {
236 hash_delete_port(portno
);
238 packetq_delfd(port
->fd_data
);
240 if (portv
[portno
]->ms
->delport
)
241 portv
[portno
]->ms
->delport(port
->fd_data
,portno
);
246 /* inactivate port: all active vlan defs cleared */
247 BAC_FORALL(validvlan
,NUMOFVLAN
,({
248 BA_CLR(vlant
[i
].bctag
,portno
);
250 fstdelport(i
,portno
);
253 if (port
->vlanuntag
< NOVLAN
) BA_CLR(vlant
[port
->vlanuntag
].bcuntag
,portno
);
262 int portflag(int op
,int f
)
266 case P_SETFLAG
: pflag
=f
; break;
267 case P_ADDFLAG
: pflag
|= f
; break;
268 case P_CLRFLAG
: pflag
&= ~f
; break;
274 /*********************** sending macro used by Core ******************/
277 #define SEND_PACKET_PORT(PORT,PACKET,LEN) \
279 struct port *Port=(PORT); \
280 struct endpoint *ep; \
281 for (ep=Port->ep; ep != NULL; ep=ep->next) \
282 if (Port->ms->sender(Port->fd_data, ep->fd_ctl, (PACKET), (LEN), ep->data, ep->port)) \
283 packetq_add(Port->ms->sender,Port->fd_data, ep->fd_ctl, (PACKET), (LEN), ep->data, ep->port); \
286 #define SEND_PACKET_PORT(PORT,PACKET,LEN) \
288 struct port *Port=(PORT); \
289 struct endpoint *ep; \
290 for (ep=Port->ep; ep != NULL; ep=ep->next) \
291 Port->ms->sender(Port->fd_data, ep->fd_ctl, (PACKET), (LEN), ep->data, ep->port); \
297 /* functions for FSTP */
298 void port_send_packet(int portno
, void *packet
, int len
)
300 SEND_PACKET_PORT(portv
[portno
],packet
,len
);
303 void portset_send_packet(bitarray portset
, void *packet
, int len
)
306 BA_FORALL(portset
,numports
,
307 SEND_PACKET_PORT(portv
[i
],packet
,len
), i
);
310 void port_set_status(int portno
, int vlan
, int status
)
312 if (BA_CHECK(vlant
[vlan
].table
,portno
)) {
313 if (status
==DISCARDING
) {
314 BA_SET(vlant
[vlan
].notlearning
,portno
);
315 BA_CLR(vlant
[vlan
].bctag
,portno
);
316 BA_CLR(vlant
[vlan
].bcuntag
,portno
);
317 } else if (status
==LEARNING
) {
318 BA_CLR(vlant
[vlan
].notlearning
,portno
);
319 BA_CLR(vlant
[vlan
].bctag
,portno
);
320 BA_CLR(vlant
[vlan
].bcuntag
,portno
);
321 } else { /*forwarding*/
322 BA_CLR(vlant
[vlan
].notlearning
,portno
);
323 if (portv
[portno
]->vlanuntag
== vlan
)
324 BA_SET(vlant
[vlan
].bcuntag
,portno
);
326 BA_SET(vlant
[vlan
].bctag
,portno
);
331 int port_get_status(int portno
, int vlan
)
333 if (BA_CHECK(vlant
[vlan
].notlearning
,portno
))
336 if (BA_CHECK(vlant
[vlan
].bctag
,portno
) ||
337 BA_CHECK(vlant
[vlan
].bcuntag
,portno
))
344 int port_getcost(int port
)
346 return portv
[port
]->cost
;
350 /************************************ CORE PACKET MGMT *****************************/
353 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
354 * | Destination | Source |81 00|pvlan| L/T | data
355 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
357 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
358 * | Destination | Source | L/T | data
359 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
361 * Destination/Source: 4 byte right shift
363 * Pointer to the packet: +4 bytes
366 #define TAG2UNTAG(P,LEN) \
367 ({ memmove((char *)(P)+4,(P),2*ETH_ALEN); LEN -= 4 ; \
368 (struct packet *)((char *)(P)+4); })
371 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
372 * | Destination | Source | L/T | data
373 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
375 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
376 * | Destination | Source |81 00|pvlan| L/T | data
377 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
378 * Destination/Source: 4 byte left shift
380 * Pointer to the packet: +4 bytes
381 * The space has been allocated in advance (just in case); all the modules
382 * read data into a bipacket.
385 #define UNTAG2TAG(P,VLAN,LEN) \
386 ({ memmove((char *)(P)-4,(P),2*ETH_ALEN); LEN += 4 ; \
387 (P)->header.src[2]=0x81; (P)->header.src[3]=0x00;\
388 (P)->header.src[4]=(VLAN >> 8); (P)->header.src[5]=(VLAN);\
389 (struct packet *)((char *)(P)-4); })
392 void handle_in_packet(int port
, struct packet
*packet
, int len
)
393 /* static void update_src(int port, struct packet *p) */
398 if (packet
->header
.proto
[0] == 0x81 && packet
->header
.proto
[1] == 0x00) {
400 vlan
=((packet
->data
[0] << 8) + packet
->data
[1]) & 0xfff;
401 if (! BA_CHECK(vlant
[vlan
].table
,port
))
402 return; /*discard unwanted packets*/
405 if ((vlan
=portv
[port
]->vlanuntag
) == NOVLAN
)
406 return; /*discard unwanted packets*/
410 if (ISBPDU(packet
)) {
411 fst_in_bpdu(port
,packet
,len
,vlan
,tagged
);
412 return; /* BPDU packets are not forwarded */
414 /* The port is in blocked status, no packet received */
416 if (BA_CHECK(vlant
[vlan
].notlearning
,port
)) return;
418 /* We don't like broadcast source addresses */
419 if(! ((IS_BROADCAST(packet
->header
.src
)) || (pflag
& HUB_TAG
))) {
421 /* int last = */ find_in_hash_update(packet
->header
.src
,vlan
,port
);
422 /* old value differs from actual input port */
423 /* if(last < 0 || (port != last)){
425 printf(" old port %d", last);
428 /* static void send_dst(int port,struct packet *packet, int len) */
429 if(IS_BROADCAST(packet
->header
.dest
) || (pflag
& HUB_TAG
) ||
430 (tarport
= find_in_hash(packet
->header
.dest
,vlan
)) < 0 ){
431 /* FST HERE! broadcast only on active ports*/
432 /* no cache or broadcast/multicast == all ports *except* the source port! */
433 /* BROADCAST: tag/untag. Broadcast the packet untouched on the ports
434 * of the same tag-ness, then transform it to the other tag-ness for the others*/
437 BA_FORALL(vlant
[vlan
].bctag
,numports
,
438 ({if (i
!= port
) SEND_PACKET_PORT(portv
[i
],packet
,len
);}),i
);
439 packet
=TAG2UNTAG(packet
,len
);
440 BA_FORALL(vlant
[vlan
].bcuntag
,numports
,
441 ({if (i
!= port
) SEND_PACKET_PORT(portv
[i
],packet
,len
);}),i
);
442 } else { /* untagged */
444 BA_FORALL(vlant
[vlan
].bcuntag
,numports
,
445 ({if (i
!= port
) SEND_PACKET_PORT(portv
[i
],packet
,len
);}),i
);
446 packet
=UNTAG2TAG(packet
,vlan
,len
);
447 BA_FORALL(vlant
[vlan
].bctag
,numports
,
448 ({if (i
!= port
) SEND_PACKET_PORT(portv
[i
],packet
,len
);}),i
);
452 /* the hash table should not generate tarport not in vlan
453 * any time a port is removed from a vlan, the port is flushed from the hash */
455 return; /*do not loop!*/
457 if (portv
[tarport
]->vlanuntag
==vlan
) /* TAG->UNTAG */
458 SEND_PACKET_PORT(portv
[tarport
],TAG2UNTAG(packet
,len
),len
);
460 SEND_PACKET_PORT(portv
[tarport
],packet
,len
);
462 if (portv
[tarport
]->vlanuntag
==vlan
) /* UNTAG->UNTAG */
463 SEND_PACKET_PORT(portv
[tarport
],packet
,len
);
464 else /* UNTAG->TAG */
465 SEND_PACKET_PORT(portv
[tarport
],UNTAG2TAG(packet
,vlan
,len
),len
);
470 /**************************************** COMMAND MANAGEMENT ****************************************/
472 static int showinfo(int fd
)
474 printoutc(fd
,"Numports=%d",numports
);
475 printoutc(fd
,"HUB=%s",(pflag
& HUB_TAG
)?"true":"false");
479 static int portsetnumports(int val
)
484 for(i
=val
;i
<numports
;i
++)
487 portv
=realloc(portv
,val
*sizeof(struct port
*));
489 printlog(LOG_ERR
,"Numport resize failed portv %s",strerror(errno
));
492 for (i
=0;i
<NUMOFVLAN
;i
++) {
493 if (vlant
[i
].table
) {
494 BA_REALLOC(vlant
[i
].table
,numports
,val
);
495 if (vlant
[i
].table
== NULL
) {
496 printlog(LOG_ERR
,"Numport resize failed vlan tables vlan table %s",strerror(errno
));
500 if (vlant
[i
].bctag
) {
501 BA_REALLOC(vlant
[i
].bctag
,numports
,val
);
502 if (vlant
[i
].bctag
== NULL
) {
503 printlog(LOG_ERR
,"Numport resize failed vlan tables vlan bctag %s",strerror(errno
));
507 if (vlant
[i
].notlearning
) {
508 BA_REALLOC(vlant
[i
].notlearning
,numports
,val
);
509 if (vlant
[i
].notlearning
== NULL
) {
510 printlog(LOG_ERR
,"Numport resize failed vlan tables vlan notlearning %s",strerror(errno
));
515 for (i
=numports
;i
<val
;i
++)
526 static int portallocatable(char *arg
)
529 if (sscanf(arg
,"%i %i",&port
,&value
) != 2)
531 if (port
< 0 || port
>= numports
)
533 if (portv
[port
] == NULL
)
536 portv
[port
]->flag
&= ~NOTINPOOL
;
538 portv
[port
]->flag
|= NOTINPOOL
;
542 static int portremove(int val
)
544 if (val
<0 || val
>=numports
)
546 if (portv
[val
] == NULL
)
548 if (portv
[val
]->ep
!= NULL
)
554 static int portcreate(int val
)
556 if (val
<0 || val
>=numports
)
558 if (portv
[val
] != NULL
)
564 static int epclose(char *arg
)
567 if (sscanf(arg
,"%i %i",&port
,&id
) != 2)
570 return close_ep(port
,id
);
573 static int print_port(int fd
,int i
,int inclinactive
)
576 if (portv
[i
] != NULL
&& (inclinactive
|| portv
[i
]->ep
!=NULL
)) {
577 printoutc(fd
,"Port %04d untagged_vlan=%04d %sACTIVE - %sUnnamed Allocatable",
578 i
,portv
[i
]->vlanuntag
,
579 portv
[i
]->ep
?"":"IN",
580 (portv
[i
]->flag
& NOTINPOOL
)?"NOT ":"");
581 for (ep
=portv
[i
]->ep
; ep
!= NULL
; ep
=ep
->next
)
582 printoutc(fd
," -- endpoint ID %04d module %-12s: %s",ep
->fd_ctl
,
583 portv
[i
]->ms
->modname
,(ep
->descr
)?ep
->descr
:"no endpoint description");
589 static int print_ptable(int fd
,char *arg
)
594 if (i
<0 || i
>=numports
)
597 return print_port(fd
,i
,0);
600 for (i
=0;i
<numports
;i
++)
606 static int print_ptableall(int fd
,char *arg
)
611 if (i
<0 || i
>=numports
)
614 return print_port(fd
,i
,1);
617 for (i
=0;i
<numports
;i
++)
623 static int portsethub(int val
)
625 (val
)?portflag(P_SETFLAG
,HUB_TAG
):portflag(P_CLRFLAG
,HUB_TAG
);
629 static int portsetvlan(char *arg
)
632 if (sscanf(arg
,"%i %i",&port
,&vlan
) != 2)
634 /* port NOVLAN is okay here, it means NO untagged traffic */
635 if (vlan
<0 || vlan
> NUMOFVLAN
|| port
< 0 || port
>= numports
)
637 if ((vlan
!= NOVLAN
&& !BAC_CHECK(validvlan
,vlan
)) || portv
[port
] == NULL
)
639 int oldvlan
=portv
[port
]->vlanuntag
;
640 portv
[port
]->vlanuntag
=NOVLAN
;
641 hash_delete_port(port
);
642 if (portv
[port
]->ep
!= NULL
) {
643 /*changing active port*/
644 if (oldvlan
!= NOVLAN
)
645 BA_CLR(vlant
[oldvlan
].bcuntag
,port
);
646 if (vlan
!= NOVLAN
) {
647 BA_SET(vlant
[vlan
].bcuntag
,port
);
648 BA_CLR(vlant
[vlan
].bctag
,port
);
651 if (oldvlan
!= NOVLAN
) fstdelport(oldvlan
,port
);
652 if (vlan
!= NOVLAN
) fstaddport(vlan
,port
,0);
655 if (oldvlan
!= NOVLAN
) BA_CLR(vlant
[oldvlan
].table
,port
);
656 if (vlan
!= NOVLAN
) BA_SET(vlant
[vlan
].table
,port
);
657 portv
[port
]->vlanuntag
=vlan
;
661 static int vlancreate_nocheck(int vlan
)
664 vlant
[vlan
].table
=BA_ALLOC(numports
);
665 vlant
[vlan
].bctag
=BA_ALLOC(numports
);
666 vlant
[vlan
].bcuntag
=BA_ALLOC(numports
);
667 vlant
[vlan
].notlearning
=BA_ALLOC(numports
);
668 if (vlant
[vlan
].table
== NULL
|| vlant
[vlan
].bctag
== NULL
||
669 vlant
[vlan
].bcuntag
== NULL
)
676 BAC_SET(validvlan
,NUMOFVLAN
,vlan
);
681 static int vlancreate(int vlan
)
683 if (vlan
> 0 && vlan
< NUMOFVLAN
-1) { /*vlan NOVLAN (0xfff a.k.a. 4095) is reserved */
684 if (BAC_CHECK(validvlan
,vlan
))
687 return vlancreate_nocheck(vlan
);
692 static int vlanremove(int vlan
)
694 if (vlan
>= 0 && vlan
< NUMOFVLAN
) {
695 if (BAC_CHECK(validvlan
,vlan
)) {
696 register int i
,used
=0;
697 BA_FORALL(vlant
[vlan
].table
,numports
,used
++,i
);
701 BAC_CLR(validvlan
,NUMOFVLAN
,vlan
);
702 free(vlant
[vlan
].table
);
703 free(vlant
[vlan
].bctag
);
704 free(vlant
[vlan
].bcuntag
);
705 free(vlant
[vlan
].notlearning
);
706 vlant
[vlan
].table
=NULL
;
707 vlant
[vlan
].bctag
=NULL
;
708 vlant
[vlan
].bcuntag
=NULL
;
709 vlant
[vlan
].notlearning
=NULL
;
721 static int vlanaddport(char *arg
)
724 if (sscanf(arg
,"%i %i",&vlan
,&port
) != 2)
726 if (vlan
<0 || vlan
>= NUMOFVLAN
-1 || port
< 0 || port
>= numports
)
728 if (!BAC_CHECK(validvlan
,vlan
) || portv
[port
] == NULL
)
730 if (portv
[port
]->ep
!= NULL
&& portv
[port
]->vlanuntag
!= vlan
) {
731 /* changing active port*/
732 BA_SET(vlant
[vlan
].bctag
,port
);
734 fstaddport(vlan
,port
,1);
737 BA_SET(vlant
[vlan
].table
,port
);
741 static int vlandelport(char *arg
)
744 if (sscanf(arg
,"%i %i",&vlan
,&port
) != 2)
746 if (vlan
<0 || vlan
>= NUMOFVLAN
-1 || port
< 0 || port
>= numports
)
748 if (!BAC_CHECK(validvlan
,vlan
) || portv
[port
] == NULL
)
750 if (portv
[port
]->vlanuntag
== vlan
)
752 if (portv
[port
]->ep
!= NULL
) {
753 /*changing active port*/
754 BA_CLR(vlant
[vlan
].bctag
,port
);
756 fstdelport(vlan
,port
);
759 BA_CLR(vlant
[vlan
].table
,port
);
760 hash_delete_port(port
);
764 #define STRSTATUS(PN,V) \
765 ((BA_CHECK(vlant[(V)].notlearning,(PN))) ? "Discarding" : \
766 (BA_CHECK(vlant[(V)].bctag,(PN)) || BA_CHECK(vlant[(V)].bcuntag,(PN))) ? \
767 "Forwarding" : "Learning")
769 static void vlanprintactive(int vlan
,int fd
)
772 printoutc(fd
,"VLAN %04d",vlan
);
774 if (pflag
& FSTP_TAG
) {
776 printoutc(fd
," ++ FST root %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n"
777 " designated %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x port %d cost %d age %d",
778 fsttab
[vlan
]->root
[0], fsttab
[vlan
]->root
[1], fsttab
[vlan
]->root
[2], fsttab
[vlan
]->root
[3],
779 fsttab
[vlan
]->root
[4], fsttab
[vlan
]->root
[5], fsttab
[vlan
]->root
[6], fsttab
[vlan
]->root
[7],
780 fsttab
[vlan
]->desbr
[0], fsttab
[vlan
]->desbr
[1], fsttab
[vlan
]->desbr
[2], fsttab
[vlan
]->desbr
[3],
781 fsttab
[vlan
]->desbr
[4], fsttab
[vlan
]->desbr
[5], fsttab
[vlan
]->desbr
[6], fsttab
[vlan
]->desbr
[7],
782 fsttab
[vlan
]->rootport
,
783 ntohl(*(u_int32_t
*)(&(fsttab
[vlan
]->rootcost
))),
784 qtime()-fsttab
[vlan
]->roottimestamp
);
785 BA_FORALL(vlant
[vlan
].table
,numports
,
786 ({ int tagged
=portv
[i
]->vlanuntag
!= vlan
;
788 printoutc(fd
," -- Port %04d tagged=%d act=%d learn=%d forw=%d cost=%d role=%s",
789 i
, tagged
, 1, !(NOTLEARNING(i
,vlan
)),
790 (tagged
)?(BA_CHECK(vlant
[vlan
].bctag
,i
) != 0):(BA_CHECK(vlant
[vlan
].bcuntag
,i
) != 0),
792 (fsttab
[vlan
]->rootport
==i
?"Root":
793 ((BA_CHECK(fsttab
[vlan
]->backup
,i
)?"Alternate/Backup":"Designated")))
799 BA_FORALL(vlant
[vlan
].table
,numports
,
800 ({ int tagged
=portv
[i
]->vlanuntag
!= vlan
;
802 printoutc(fd
," -- Port %04d tagged=%d active=1 status=%s", i
, tagged
,
810 static int vlanprint(int fd
,char *arg
)
815 if (vlan
>= 0 && vlan
< NUMOFVLAN
-1) {
816 if (BAC_CHECK(validvlan
,vlan
))
817 vlanprintactive(vlan
,fd
);
823 BAC_FORALLFUN(validvlan
,NUMOFVLAN
,vlanprintactive
,fd
);
827 static void vlanprintelem(int vlan
,int fd
)
830 printoutc(fd
,"VLAN %04d",vlan
);
831 BA_FORALL(vlant
[vlan
].table
,numports
,
832 printoutc(fd
," -- Port %04d tagged=%d active=%d status=%s",
833 i
, portv
[i
]->vlanuntag
!= vlan
, portv
[i
]->ep
!= NULL
, STRSTATUS(i
,vlan
)),i
);
836 static int vlanprintall(int fd
,char *arg
)
841 if (vlan
> 0 && vlan
< NUMOFVLAN
-1) {
842 if (BAC_CHECK(validvlan
,vlan
))
843 vlanprintelem(vlan
,fd
);
849 BAC_FORALLFUN(validvlan
,NUMOFVLAN
,vlanprintelem
,fd
);
853 /* NOT sure about the effects of changing address on FSTP */
856 static int setmacaddr(char *strmac
)
858 int maci
[ETH_ALEN
],rv
;
860 if (index(strmac
,':') != NULL
)
861 rv
=sscanf(strmac
,"%x:%x:%x:%x:%x:%x", maci
+0, maci
+1, maci
+2, maci
+3, maci
+4, maci
+5);
863 rv
=sscanf(strmac
,"%x.%x.%x.%x.%x.%x", maci
+0, maci
+1, maci
+2, maci
+3, maci
+4, maci
+5);
868 for (i
=0;i
<ETH_ALEN
;i
++)
869 switchmac
[i
]=maci
[i
];
876 static struct comlist cl
[]={
877 {"port","============","PORT STATUS MENU",NULL
,NOARG
},
878 {"port/showinfo","","show hash info",showinfo
,NOARG
|WITHFD
},
879 {"port/setnumports","N","set the number of ports",portsetnumports
,INTARG
},
880 /*{"port/setmacaddr","MAC","set the switch MAC address",setmacaddr,STRARG},*/
881 {"port/sethub","0/1","1=HUB 0=switch",portsethub
,INTARG
},
882 {"port/setvlan","N VLAN","set port VLAN (untagged)",portsetvlan
,STRARG
},
883 {"port/create","N","create the port N (inactive)",portcreate
,INTARG
},
884 {"port/remove","N","remove the port N",portremove
,INTARG
},
885 {"port/allocatable","N 0/1","Is the port allocatable as unnamed? 1=Y 0=N",portallocatable
,STRARG
},
886 {"port/epclose","N ID","remove the endpoint port N/id ID",epclose
,STRARG
},
887 {"port/print","[N]","print the port/endpoint table",print_ptable
,STRARG
|WITHFD
},
888 {"port/allprint","[N]","print the port/endpoint table (including inactive port)",print_ptableall
,STRARG
|WITHFD
},
889 {"vlan","============","VLAN MANAGEMENT MENU",NULL
,NOARG
},
890 {"vlan/create","N","create the VLAN with tag N",vlancreate
,INTARG
},
891 {"vlan/remove","N","remove the VLAN with tag N",vlanremove
,INTARG
},
892 {"vlan/addport","N PORT","add port to the vlan N (tagged)",vlanaddport
,STRARG
},
893 {"vlan/delport","N PORT","add port to the vlan N (tagged)",vlandelport
,STRARG
},
894 {"vlan/print","[N]","print the list of defined vlan",vlanprint
,STRARG
|WITHFD
},
895 {"vlan/allprint","[N]","print the list of defined vlan (including inactive port)",vlanprintall
,STRARG
|WITHFD
},
898 void port_init(int initnumports
)
900 if((numports
=initnumports
) <= 0) {
901 printlog(LOG_ERR
,"The switch must have at least 1 port\n");
904 portv
=calloc(numports
,sizeof(struct port
*));
906 validvlan
=BAC_ALLOC(NUMOFVLAN
);
907 if (portv
==NULL
|| validvlan
== NULL
) {
908 printlog(LOG_ERR
,"ALLOC port data structures");
911 if (vlancreate_nocheck(0) != 0) {
912 printlog(LOG_ERR
,"ALLOC vlan port data structures");