1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
|
/*
* 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) */
#define No_of_ports 8
/* 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 300
/*
* 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
#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
typedef struct {
unsigned short protocol_id;
unsigned char protocol_version_id;
unsigned char type;
unsigned char flags;
#define TOPOLOGY_CHANGE 0x01
#define TOPOLOGY_CHANGE_ACK 0x80
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) */
} Config_bpdu;
/** 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 topology_change_detected; /* (4.5.3.11) */
unsigned int topology_change; /* (4.5.3.12) */
unsigned short topology_change_time; /* (4.5.3.13) */
unsigned short hold_time; /* (4.5.3.14) */
unsigned int top_change;
unsigned int top_change_detected;
} 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) */
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 int flags;
#define FDB_ENT_VALID 0x01
/* 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;
};
#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
struct br_stat {
unsigned int flags;
Bridge_data bridge_data;
Port_data port_data[No_of_ports];
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 ? */
};
/* 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 */
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 /* arg1 = port */
#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
/* prototypes of all bridging functions... */
void transmit_config(int port_no);
int root_bridge(void);
int supersedes_port_info(int port_no, Config_bpdu *config);
void record_config_information(int port_no, Config_bpdu *config);
void record_config_timeout_values(Config_bpdu *config);
void config_bpdu_generation(void);
int designated_port(int port_no);
void reply(int port_no);
void transmit_tcn(void);
void configuration_update(void);
void root_selection(void);
void designated_port_selection(void);
void become_designated_port(int port_no);
void port_state_selection(void);
void make_forwarding(int port_no);
void topology_change_detection(void);
void topology_change_acknowledged(void);
void acknowledge_topology_change(int port_no);
void make_blocking(int port_no);
void set_port_state(int port_no, int state);
void received_config_bpdu(int port_no, Config_bpdu *config);
void received_tcn_bpdu(int port_no, Tcn_bpdu *tcn);
void hello_timer_expiry(void);
void message_age_timer_expiry(int port_no);
void forward_delay_timer_expiry(int port_no);
int designated_for_some_port(void);
void tcn_timer_expiry(void);
void topology_change_timer_expiry(void);
void hold_timer_expiry(int port_no);
void br_init(void);
void br_init_port(int port_no);
void enable_port(int port_no);
void disable_port(int port_no);
void set_bridge_priority(bridge_id_t *new_bridge_id);
void set_port_priority(int port_no, unsigned short new_port_id);
void set_path_cost(int port_no, unsigned short path_cost);
void start_hello_timer(void);
void stop_hello_timer(void);
int hello_timer_expired(void);
void start_tcn_timer(void);
void stop_tcn_timer(void);
int tcn_timer_expired(void);
void start_topology_change_timer(void);
void stop_topology_change_timer(void);
int topology_change_timer_expired(void);
void start_message_age_timer(int port_no, unsigned short message_age);
void stop_message_age_timer(int port_no);
int message_age_timer_expired(int port_no);
void start_forward_delay_timer(int port_no);
void stop_forward_delay_timer(int port_no);
int forward_delay_timer_expired(int port_no);
void start_hold_timer(int port_no);
void stop_hold_timer(int port_no);
int hold_timer_expired(int port_no);
struct fdb *br_avl_find_addr(unsigned char addr[6]);
int br_avl_insert (struct fdb * new_node);
int br_avl_remove (struct fdb * node_to_delete);
int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu);
int send_config_bpdu(int port_no, Config_bpdu *config_bpdu);
int find_port(struct device *dev);
int br_flood(struct sk_buff *skb, int port);
int br_drop(struct sk_buff *skb);
int br_learn(struct sk_buff *skb, int port); /* 3.8 */
int br_receive_frame(struct sk_buff *skb); /* 3.5 */
int br_tx_frame(struct sk_buff *skb);
int br_ioctl(unsigned int cmd, void *arg);
int br_protocol_ok(unsigned short protocol);
void free_fdb(struct fdb *);
struct fdb *get_fdb(void);
/* externs */
extern struct br_stat br_stats;
|