📄 stp.c
字号:
/* stp - spanning tree protocol * * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/if_ether.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/spinlock.h>#include <asm/unaligned.h>#include <linux/netfilter.h>#include <ttype.h>#include <switch.h>#include "ieee802_1d.h"#include "stp.h"#include "wrpmac.h"#include "wrpport.h"#include "wrpstp.h"#include "wrpsys.h"#include "wrptype.h"#include "../mx/via.h"#include "../mx/mx.h"#undef STP_DEBUG#define STP_PORT_MAX 27extern void (*gvrp_stp_port_forwarding)(int );extern void (*gvrp_stp_port_disabled)(int );extern void (*gmrp_stp_port_forwarding)(int );extern void (*gmrp_stp_port_disabled)(int );extern void (*igmp_stp_port_forwarding)(int );extern void (*igmp_stp_port_disabled)(int );extern int num_tcn;extern unsigned long last_tcn;extern struct nf_sockopt_ops stp_sockopts; struct stp_t stp_info;unsigned char bridge_mac[6];unsigned long ulSpanTreeTickScaling;unsigned long ulMaxNoPorts = 0; /* port threads will increase this */static int periodical_thread_pid;static int port_thread_pid;static int stp_tick_enable;static int restart;//SNMP Bridge MIBint forward_transition[STP_PORT_MAX];static void sleep(unsigned howlong) { if(in_interrupt()) { return; } current->state = TASK_INTERRUPTIBLE; schedule_timeout(howlong); }/* this thread will use portdrv to find out any port changes * and report them to the ieee 802.1d code. */static spinlock_t stp_ieee_sem;static int stp_port_thread(void * vp) { int i; int enabled; Cost c; UINT8 byAutoAbl, byPortAbl; BOOL bPortEbl; BOOL status[STP_PORT_MAX]; UINT8 autoabl[STP_PORT_MAX],portabl[STP_PORT_MAX]; for(i=0;i<STP_PORT_MAX;i++) { K_PortGetLink(i, (PBOOL) &(status[i])); /* // 2007-3-22 Steve changed, need it for module ports? if(i>=24) status[i]=BIObIsRegSpecBitOn(PHY_LINK_STATUS, i); HIbPORTCTL_GetPortAbl((UINT8) i, &(autoabl[i]), &(portabl[i])); */ portabl[i] = SWPORT_byGetSpdDpx(i); K_PortGetNego(i, &(autoabl[i])); enabled = 0; c=0;// printk("STP : Port %d PortEbl=%d\n",i+1,status[i]); { if (status[i] == FALSE) {#ifdef STP_DEBUG printk("STP : Port %d disable\n",i);#endif enabled = 0; } else if ((portabl[i]== PORTCTL_10M_HALF) || (portabl[i]== PORTCTL_10M_FULL)) {#ifdef STP_DEBUG printk("STP : Port %d 10M\n",i);#endif c= 100; /* (8.8.6) Table 8.5 */ enabled= 1; } else if ((portabl[i]== PORTCTL_100M_HALF) || (portabl[i]== PORTCTL_100M_FULL)) {#ifdef STP_DEBUG printk("STP : Port %d 100M\n",i);#endif//many product set to 10// c= 19; /* (8.8.6) Table 8.5 */ c= 10; /* (8.8.6) Table 8.5 */ enabled= 1; } else if ((portabl[i]== PORTCTL_1000M_HALF) || (portabl[i]== PORTCTL_1000M_FULL)) {#ifdef STP_DEBUG printk("STP : Port %d 1000M\n",i);#endif c= 4; /* (8.8.6) Table 8.5 */ enabled= 1; } else { /* warn and disable if bad bitfields */ #ifdef STP_DEBUG printk("STP:Error Value %d\n", portabl[i]);#endif enabled= 0; } }// printk("STP : port = %d, enabled = %d, cost = %d\n", i+1, enabled, c); spin_lock(&stp_ieee_sem); /* protect the ieee802.1d code */ if (enabled) {// printk("port %d is enabled cost=%d\n", i, c); enable_port(i + 1); set_path_cost(i + 1, c); } else {// printk("port %d is disabled\n", i);// set_path_cost(i + 1, DEF_PATH_COST); disable_port(i + 1); } spin_unlock(&stp_ieee_sem); } while(1) { if(!stp_tick_enable) {sleep(1000); continue;} for(i=0;i<STP_PORT_MAX;i++) { // 2007-3-22 SteveLin changed // HIbPORTCTL_GetPortEbl((UINT8) i, &bPortEbl); bPortEbl = SWPORT_bGetPortEn(i); /* // 2007-3-22 SteveLin commented, still need for module? if (i >= 24) bPortEbl=BIObIsRegSpecBitOn(PHY_LINK_STATUS, i); */ // 2007-3-22 SteveLin changed // HIbPORTCTL_GetPortAbl((UINT8) i, &byAutoAbl, &byPortAbl); byPortAbl = SWPORT_byGetSpdDpx(i); K_PortGetNego(i, &byAutoAbl); #ifdef STP_DEBUG// printk("STP : Port %d PortEbl=%d\n",i+1,bPortEbl);#endif if(!restart && (status[i] == bPortEbl) && (byAutoAbl == autoabl[i]) && (byPortAbl == portabl[i]) ) { sleep(10); continue; } if(restart) restart--; status[i]=bPortEbl; autoabl[i]=byAutoAbl; portabl[i]=byPortAbl; enabled = 0; c=0; { if (bPortEbl == FALSE) {#ifdef STP_DEBUG printk("STP : Port %d disable\n",i);#endif enabled = 0; } else if ((byPortAbl== PORTCTL_10M_HALF) || (byPortAbl== PORTCTL_10M_FULL)) {#ifdef STP_DEBUG printk("STP : Port %d 10M\n",i);#endif c= 100; /* (8.8.6) Table 8.5 */ enabled= 1; } else if ((byPortAbl== PORTCTL_100M_HALF) || (byPortAbl== PORTCTL_100M_FULL)) {#ifdef STP_DEBUG printk("STP : Port %d 100M\n",i);#endif //many product set to 10// c= 19; /* (8.8.6) Table 8.5 */ c= 10; /* (8.8.6) Table 8.5 */ enabled= 1; } else if ((byPortAbl== PORTCTL_1000M_HALF) || (byPortAbl== PORTCTL_1000M_FULL)) {#ifdef STP_DEBUG printk("STP : Port %d 1000M\n",i);#endif c= 4; /* (8.8.6) Table 8.5 */ enabled= 1; } else { /* warn and disable if bad bitfields */ #ifdef STP_DEBUG printk("STP:Error Value %d\n", byPortAbl);#endif enabled= 0; } }// printk("STP : port = %d, enabled = %d, cost = %d\n", i+1, enabled, c); spin_lock(&stp_ieee_sem); /* protect the ieee802.1d code */ if (enabled) {// printk("port %d is enabled cost=%d\n", i, c); enable_port(i + 1); set_path_cost(i + 1, c); } else {// printk("port %d is disabled\n", i); disable_port(i + 1); } spin_unlock(&stp_ieee_sem); } } return 0; }/* periodically run */static int stp_periodical_thread(void * vp) { while(1) { if(!stp_tick_enable) {sleep(1000); continue;}// printk("STP: Tick\n"); spin_lock(&stp_ieee_sem); /* protect the ieee802.1d code */ STP_tick();// printk("STP: Tick3\n"); spin_unlock(&stp_ieee_sem);// printk("STP: Tick4\n");// sleep(10);// sleep(23); sleep(25); } return 0;}/* The CallBack function. * This function will get bpdu packets from * the VT6526 and report them to the ieee 802.1d code. *//****************************************************************/static int stp(struct sk_buff *skb) {#ifdef STP_DEBUG printk("STP: program receives a packet!! %d %d %d %d %d %d\n",VIA_P(skb)->wSize,VIA_P(skb)->wVid,VIA_P(skb)->byPriority,VIA_P(skb)->bySrcPortId,VIA_P(skb)->byFwdReason,VIA_P(skb)->bIfTagged);#endif /* Process the BPDU packet */ { Config_bpdu receivedConfigBpdu; Tcn_bpdu receivedTcnBpdu; Bpdu_type bpduMessageType; Protocol_version protocolVersion; int port_no; unsigned int uiProtocolIdentifier; unsigned char * pucEthernet; pucEthernet = (unsigned char *)skb->mac.raw;// printk("len=%d\n",(ntohs(*((unsigned short*)(pucEthernet+12)))) );// if (VIA_P(skb)->wSize >= 17) if ((ntohs(*((unsigned short*)(pucEthernet+12)))) >= 17) { unsigned char * pucBPDU; pucEthernet = (unsigned char *)skb->mac.raw; if(VIA_P(skb)->bIfTagged) pucBPDU = &pucEthernet[17 + 4 /* ignore the silly VLAN tag */]; else pucBPDU = &pucEthernet[17]; /* Find BPDU Protocol Identifier. * First and second byte in configuration message. */ uiProtocolIdentifier = ((unsigned int)pucBPDU[0] << 8) + (unsigned int)pucBPDU[1]; /* Find BPDU Protocol Version. * Third byte in configuration message. */ protocolVersion = pucBPDU[2]; /* Find BPDU message type. * Fourth byte in configuration message. */ bpduMessageType = pucBPDU[3];#ifdef DUMP_RECEIVED_BPDU /* test */ { int i; for (i = 0;i < 32;i++) { if ((i % 16) == 0) { fprintf(stderr, "\n%02x ",pucEthernet[i]); } else { fprintf(stderr, "%02x ",pucEthernet[i]); } } fprintf(stderr, "\n"); }#endif if (uiProtocolIdentifier == 0) { switch (bpduMessageType) { case Config_bpdu_type:#ifdef STP_DEBUG printk("STP: program receives a BPDU packet!! size:%d vid:%d priority:%d portid:%d reason:%d iftag:%d\n",VIA_P(skb)->wSize,VIA_P(skb)->wVid,VIA_P(skb)->byPriority,VIA_P(skb)->bySrcPortId,VIA_P(skb)->byFwdReason,VIA_P(skb)->bIfTagged);#endif /* Check BPDU - is it a sane packet ? */ {// if (!(VIA_P(skb)->wSize >= CONFIG_BPDU_MESSAGE_BYTES)) //by flash, pass ANVL test case 8.2// printk("len=%d bIfTagged=%d\n",(ntohs(*((unsigned short*)(pucEthernet+12)))),VIA_P(skb)->bIfTagged ); if(VIA_P(skb)->bIfTagged) { if ((ntohs(*((unsigned short*)(pucEthernet+12)))) <= 34+3+4) { break; } } else { if ((ntohs(*((unsigned short*)(pucEthernet+12)))) <= 34+3) {// printk("too short \n"); break; } } /* check for invalid flag */ if ( (unsigned long)pucBPDU[4] & 0x7E) {#ifdef STP_DEBUG printk("STP Discard Packet! BPDU Flag invalid\n");#endif break; } } /* Copying data from message bytes to * config structure in 802.1D code */ { int i = 4; /* start of Flags */ receivedConfigBpdu.topology_change_acknowledgment = (unsigned long)pucBPDU[i] & 0x80; receivedConfigBpdu.topology_change = (unsigned long)pucBPDU[i++] & 0x01; receivedConfigBpdu.root_id.four_octets[0] = (unsigned long)pucBPDU[i++] << 24; receivedConfigBpdu.root_id.four_octets[0] |= (unsigned long)pucBPDU[i++] << 16; receivedConfigBpdu.root_id.four_octets[0] |= (unsigned long)pucBPDU[i++] << 8; receivedConfigBpdu.root_id.four_octets[0] |= (unsigned long)pucBPDU[i++] << 0; receivedConfigBpdu.root_id.four_octets[1] = (unsigned long)pucBPDU[i++] << 24; receivedConfigBpdu.root_id.four_octets[1] |= (unsigned long)pucBPDU[i++] << 16; receivedConfigBpdu.root_id.four_octets[1] |= (unsigned long)pucBPDU[i++] << 8; receivedConfigBpdu.root_id.four_octets[1] |= (unsigned long)pucBPDU[i++] << 0; receivedConfigBpdu.root_path_cost = (unsigned long)pucBPDU[i++] << 24; receivedConfigBpdu.root_path_cost |= (unsigned long)pucBPDU[i++] << 16; receivedConfigBpdu.root_path_cost |= (unsigned long)pucBPDU[i++] << 8; receivedConfigBpdu.root_path_cost |= (unsigned long)pucBPDU[i++] << 0; receivedConfigBpdu.bridge_id.four_octets[0] = (unsigned long)pucBPDU[i++] << 24; receivedConfigBpdu.bridge_id.four_octets[0] |= (unsigned long)pucBPDU[i++] << 16; receivedConfigBpdu.bridge_id.four_octets[0] |= (unsigned long)pucBPDU[i++] << 8; receivedConfigBpdu.bridge_id.four_octets[0] |= (unsigned long)pucBPDU[i++] << 0; receivedConfigBpdu.bridge_id.four_octets[1] = (unsigned long)pucBPDU[i++] << 24; receivedConfigBpdu.bridge_id.four_octets[1] |= (unsigned long)pucBPDU[i++] << 16; receivedConfigBpdu.bridge_id.four_octets[1] |= (unsigned long)pucBPDU[i++] << 8; receivedConfigBpdu.bridge_id.four_octets[1] |= (unsigned long)pucBPDU[i++] << 0; receivedConfigBpdu.port_id = (unsigned short)((unsigned short)pucBPDU[i++] << 8); receivedConfigBpdu.port_id |= (unsigned short)pucBPDU[i++] << 0; receivedConfigBpdu.message_age = (unsigned short)((unsigned short)pucBPDU[i++] << 8); receivedConfigBpdu.message_age |= (unsigned short)pucBPDU[i++] << 0; receivedConfigBpdu.max_age = (unsigned short)((unsigned short)pucBPDU[i++] << 8); receivedConfigBpdu.max_age |= (unsigned short)pucBPDU[i++] << 0; receivedConfigBpdu.hello_time = (unsigned short)((unsigned short)pucBPDU[i++] << 8); receivedConfigBpdu.hello_time |= (unsigned short)pucBPDU[i++] << 0; receivedConfigBpdu.forward_delay = (unsigned short)((unsigned short)pucBPDU[i++] << 8); receivedConfigBpdu.forward_delay |= (unsigned short)pucBPDU[i++] << 0; (void)i; } /* Set BPDU message type */ receivedConfigBpdu.type = bpduMessageType; /* Copy the topology change bits in the messages * 5:th byte to the right fields in the structure */ receivedConfigBpdu.topology_change_acknowledgment = (pucBPDU[4] & 0x80) ? 1 : 0 ; receivedConfigBpdu.topology_change = (pucBPDU[4] & 0x1) ? 1 : 0 ; if(receivedConfigBpdu.topology_change) { num_tcn++; last_tcn=jiffies; K_MacClrTbl(MAC_CLR_DYNMC); } /* Convert VIA port numbering (from 0) * to port_no numbering from 1 */ port_no = VIA_P(skb)->bySrcPortId + 1; //VIA driver start at 0 but IEEE codes start at 1 /* Call code supplied in 802.1D */ if (receivedConfigBpdu.message_age < receivedConfigBpdu.max_age) { spin_lock(&stp_ieee_sem); /* protect the ieee802.1d code *///printk("received_config_bpdu\n"); received_config_bpdu(port_no, &receivedConfigBpdu); spin_unlock(&stp_ieee_sem); } break; case Tcn_bpdu_type:#ifdef STP_DEBUG printk("STP: program receives a TCN packet!! size:%d vid:%d priority:%d portid:%d reason:%d iftag:%d\n",VIA_P(skb)->wSize,VIA_P(skb)->wVid,VIA_P(skb)->byPriority,VIA_P(skb)->bySrcPortId,VIA_P(skb)->byFwdReason,VIA_P(skb)->bIfTagged);#endif num_tcn++; last_tcn=jiffies;// not need, by flash// K_MacClrTbl(MAC_CLR_DYNMC); /* Check BPDU */ { if (!(VIA_P(skb)->wSize >= 4)) { break; } } /* Fill in Tcn_bpdu from message */ receivedTcnBpdu.type = bpduMessageType; //VIA driver start at 0 but IEEE codes start at 1 port_no = VIA_P(skb)->bySrcPortId + 1; /* Call code supplied in 802.1D */ spin_lock(&stp_ieee_sem); /* protect the ieee802.1d code */ received_tcn_bpdu( port_no, &receivedTcnBpdu); spin_unlock(&stp_ieee_sem); break; default:#ifdef STP_DEBUG printk("- Ignored bpduMessageType 0x%02x.\n", (unsigned int) bpduMessageType);#endif break; } /* switch */ } /* if */ } /* if */ } return MX_DROP; }void SendConfigBpdu(Int port_no, Config_bpdu *bpdu) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -