/* * Constants and structure definitions for the bridging code */ #if !defined(One) #define Zero 0 #define One 1 #endif /* !defined(One) */ #if !defined(TRUE) #define FALSE 0 #define TRUE 1 #endif /* !defined(TRUE) */ /** port states. **/ #define Disabled 0 /* (4.4 5) */ #define Listening 1 /* (4.4.2) */ #define Learning 2 /* (4.4.3) */ #define Forwarding 3 /* (4 4 4) */ #define Blocking 4 /* (4.4.1) */ /* MAG Yich! Easiest way of giving a configurable number of ports * If you want more than 32, change BR_MAX_PORTS and recompile brcfg! */ #define BR_MAX_PORTS (32) #if CONFIG_BRIDGE_NUM_PORTS > BR_MAX_PORTS #undef CONFIG_BRIDGE_NUM_PORTS #define CONFIG_BRIDGE_NUM_PORTS BR_MAX_PORTS #endif #define No_of_ports CONFIG_BRIDGE_NUM_PORTS /* arbitrary choice, to allow the code below to compile */ #define All_ports (No_of_ports + 1) /* * We time out our entries in the FDB after this many seconds. */ #define FDB_TIMEOUT 20 /* JRP: 20s as NSC bridge code, was 300 for Linux */ /* * the following defines are the initial values used when the * bridge is booted. These may be overridden when this bridge is * not the root bridge. These are the recommended default values * from the 802.1d specification. */ #define BRIDGE_MAX_AGE 20 #define BRIDGE_HELLO_TIME 2 #define BRIDGE_FORWARD_DELAY 15 #define HOLD_TIME 1 /* broacast/multicast storm limitation. This per source. */ #define MAX_MCAST_PER_PERIOD 4 #define MCAST_HOLD_TIME (10*HZ/100) #define Default_path_cost 10 /* * minimum increment possible to avoid underestimating age, allows for BPDU * transmission time */ #define Message_age_increment 1 #define No_port 0 /* * reserved value for Bridge's root port parameter indicating no root port, * used when Bridge is the root - also used to indicate the source when * a frame is being generated by a higher layer protocol on this host */ /** Configuration BPDU Parameters (4.5.1) **/ typedef struct { union { struct { unsigned short priority; unsigned char ula[6]; } p_u; unsigned int id[2]; } bi; } bridge_id_t; #define BRIDGE_PRIORITY bi.p_u.priority #define BRIDGE_ID_ULA bi.p_u.ula #define BRIDGE_ID bi.id /* JRP: on the network the flags field is between "type" and "root_id" * this is unfortunated! To make the code portable to a RISC machine * the pdus are now massaged a little bit for processing */ #define TOPOLOGY_CHANGE 0x01 #define TOPOLOGY_CHANGE_ACK 0x80 #define BRIDGE_BPDU_8021_CONFIG_SIZE 35 /* real size */ #define BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET 4 #define BRIDGE_BPDU_8021_PROTOCOL_ID 0 #define BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID 0 #define BRIDGE_LLC1_HS 3 #define BRIDGE_LLC1_DSAP 0x42 #define BRIDGE_LLC1_SSAP 0x42 #define BRIDGE_LLC1_CTRL 0x03 typedef struct { unsigned short protocol_id; unsigned char protocol_version_id; unsigned char type; bridge_id_t root_id; /* (4.5.1.1) */ unsigned int root_path_cost; /* (4.5.1.2) */ bridge_id_t bridge_id; /* (4.5.1.3) */ unsigned short port_id; /* (4.5.1.4) */ unsigned short message_age; /* (4.5.1.5) */ unsigned short max_age; /* (4.5.1.6) */ unsigned short hello_time; /* (4.5.1.7) */ unsigned short forward_delay; /* (4.5.1.8) */ unsigned char top_change_ack; unsigned char top_change; } Config_bpdu; #ifdef __LITTLE_ENDIAN #define config_bpdu_hton(config_bpdu) \ (config_bpdu)->root_path_cost = htonl((config_bpdu)->root_path_cost); \ (config_bpdu)->port_id = htons((config_bpdu)->port_id); \ (config_bpdu)->message_age = htons((config_bpdu)->message_age); \ (config_bpdu)->max_age = htons((config_bpdu)->max_age); \ (config_bpdu)->hello_time = htons((config_bpdu)->hello_time); \ (config_bpdu)->forward_delay = htons((config_bpdu)->forward_delay); #else #define config_bpdu_hton(config_bpdu) #endif #define config_bpdu_ntoh config_bpdu_hton /** Topology Change Notification BPDU Parameters (4.5.2) **/ typedef struct { unsigned short protocol_id; unsigned char protocol_version_id; unsigned char type; } Tcn_bpdu; #define BPDU_TYPE_CONFIG 0 #define BPDU_TYPE_TOPO_CHANGE 128 /** Bridge Parameters (4.5.3) **/ typedef struct { bridge_id_t designated_root; /* (4.5.3.1) */ unsigned int root_path_cost; /* (4.5.3.2) */ unsigned int root_port; /* (4.5.3.3) */ unsigned short max_age; /* (4.5.3.4) */ unsigned short hello_time; /* (4.5.3.5) */ unsigned short forward_delay; /* (4.5.3.6) */ bridge_id_t bridge_id; /* (4.5.3.7) */ unsigned short bridge_max_age; /* (4.5.3.8) */ unsigned short bridge_hello_time; /* (4.5.3.9) */ unsigned short bridge_forward_delay; /* (4.5.3.10) */ unsigned int top_change_detected; /* (4.5.3.11) */ unsigned int top_change; /* (4.5.3.12) */ unsigned short topology_change_time; /* (4.5.3.13) */ unsigned short hold_time; /* (4.5.3.14) */ unsigned int instance; } Bridge_data; /** Port Parameters (4.5.5) **/ typedef struct { unsigned short port_id; /* (4.5.5.1) */ unsigned int state; /* (4.5.5.2) */ unsigned int path_cost; /* (4.5.5.3) */ bridge_id_t designated_root; /* (4.5.5.4) */ unsigned int designated_cost; /* (4.5.5.5) */ bridge_id_t designated_bridge; /* (4.5.5.6) */ unsigned short designated_port; /* (4.5.5.7) */ unsigned int top_change_ack; /* (4.5.5.8) */ unsigned int config_pending; /* (4.5.5.9) */ bridge_id_t ifmac; unsigned int admin_state; char ifname[IFNAMSIZ]; /* Make life easier for brcfg */ struct device *dev; struct fdb *fdb; /* head of per port fdb chain */ } Port_data; /** types to support timers for this pseudo-implementation. **/ typedef struct { unsigned int active; /* timer in use. */ unsigned int value; /* current value of timer, * counting up. */ } Timer; struct fdb { unsigned char ula[6]; unsigned char pad[2]; unsigned short port; unsigned int timer; unsigned short flags; #define FDB_ENT_VALID 0x01 unsigned short mcast_count; unsigned int mcast_timer; /* oldest xxxxxcast */ /* AVL tree of all addresses, sorted by address */ short fdb_avl_height; struct fdb *fdb_avl_left; struct fdb *fdb_avl_right; /* linked list of addresses for each port */ struct fdb *fdb_next; }; /* data returned on BRCMD_DISPLAY_FDB */ struct fdb_info { unsigned char ula[6]; unsigned char port; unsigned char flags; unsigned int timer; }; struct fdb_info_hdr { int copied; /* nb of entries copied to user */ int not_copied; /* when user buffer is too small */ int cmd_time; }; #define IS_BRIDGED 0x2e #define BR_MAX_PROTOCOLS 32 #define BR_MAX_PROT_STATS BR_MAX_PROTOCOLS /* policy values for policy field */ #define BR_ACCEPT 1 #define BR_REJECT 0 /* JRP: extra statistics for debug */ typedef struct { /* br_receive_frame counters */ int port_disable_up_stack; int rcv_bpdu; int notForwarding; int forwarding_up_stack; int unknown_state; /* br_tx_frame counters */ int port_disable; int port_not_disable; /* br_forward counters */ int local_multicast; int forwarded_multicast; /* up stack as well */ int flood_unicast; int aged_flood_unicast; int forwarded_unicast; int forwarded_unicast_up_stack; int forwarded_ip_up_stack; int forwarded_ip_up_stack_lie; /* received on alternate device */ int arp_for_local_mac; int drop_same_port; int drop_same_port_aged; int drop_multicast; } br_stats_counter; struct br_stat { unsigned int flags; Bridge_data bridge_data; unsigned int policy; unsigned int exempt_protocols; unsigned short protocols[BR_MAX_PROTOCOLS]; unsigned short prot_id[BR_MAX_PROT_STATS]; /* Protocol encountered */ unsigned int prot_counter[BR_MAX_PROT_STATS]; /* How many packets ? */ br_stats_counter packet_cnts; unsigned int num_ports; Port_data port_data[BR_MAX_PORTS + 1]; }; /* defined flags for br_stat.flags */ #define BR_UP 0x0001 /* bridging enabled */ #define BR_DEBUG 0x0002 /* debugging enabled */ #define BR_PROT_STATS 0x0004 /* protocol statistics enabled */ #define BR_STP_DISABLED 0x0008 /* Spanning tree protocol disabled */ struct br_cf { unsigned int cmd; unsigned int arg1; unsigned int arg2; }; /* defined cmds */ #define BRCMD_BRIDGE_ENABLE 1 #define BRCMD_BRIDGE_DISABLE 2 #define BRCMD_PORT_ENABLE 3 /* arg1 = port */ #define BRCMD_PORT_DISABLE 4 /* arg1 = port */ #define BRCMD_SET_BRIDGE_PRIORITY 5 /* arg1 = priority */ #define BRCMD_SET_PORT_PRIORITY 6 /* arg1 = port, arg2 = priority */ #define BRCMD_SET_PATH_COST 7 /* arg1 = port, arg2 = cost */ #define BRCMD_DISPLAY_FDB 8 #define BRCMD_ENABLE_DEBUG 9 #define BRCMD_DISABLE_DEBUG 10 #define BRCMD_SET_POLICY 11 /* arg1 = default policy (1==bridge all) */ #define BRCMD_EXEMPT_PROTOCOL 12 /* arg1 = protocol (see net/if_ether.h) */ #define BRCMD_ENABLE_PROT_STATS 13 #define BRCMD_DISABLE_PROT_STATS 14 #define BRCMD_ZERO_PROT_STATS 15 #define BRCMD_TOGGLE_STP 16 #define BRCMD_IF_ENABLE 17 /* arg1 = if_index */ #define BRCMD_IF_DISABLE 18 /* arg1 = if_index */ #define BRCMD_SET_IF_PRIORITY 19 /* arg1 = if_index, arg2 = priority */ #define BRCMD_SET_IF_PATH_COST 20 /* arg1 = if_index, arg2 = cost */ /* prototypes of exported bridging functions... */ #ifdef __KERNEL__ void br_init(void); int br_receive_frame(struct sk_buff *skb); /* 3.5 */ int br_tx_frame(struct sk_buff *skb); int brg_init(void); int br_ioctl(unsigned int cmd, void *arg); void requeue_fdb(struct fdb *node, int new_port); struct fdb *br_avl_find_addr(unsigned char addr[6]); struct fdb *br_avl_insert (struct fdb * new_node); void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length); int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy); void br_avl_delete_by_port(int port); int br_call_bridge(struct sk_buff *skb, unsigned short type); void br_spacedevice_register(void); /* externs */ extern struct br_stat br_stats; extern Port_data port_info[]; #endif