Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
a8c505ff
Commit
a8c505ff
authored
Apr 29, 2003
by
Stephen Hemminger
Committed by
David S. Miller
Apr 29, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[BRIDGE}: Change bridge forwarding table to use hlist.
parent
07211edd
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
51 additions
and
71 deletions
+51
-71
include/linux/list.h
include/linux/list.h
+4
-0
net/bridge/br_fdb.c
net/bridge/br_fdb.c
+45
-68
net/bridge/br_private.h
net/bridge/br_private.h
+2
-3
No files found.
include/linux/list.h
View file @
a8c505ff
...
@@ -437,6 +437,10 @@ static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node
...
@@ -437,6 +437,10 @@ static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node
for (pos = (head)->first; pos; \
for (pos = (head)->first; pos; \
pos = pos->next)
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; n = pos ? pos->next : 0, pos; \
pos = n)
#else
#else
#warning "don't include kernel headers in userspace"
#warning "don't include kernel headers in userspace"
#endif
/* __KERNEL__ */
#endif
/* __KERNEL__ */
...
...
net/bridge/br_fdb.c
View file @
a8c505ff
...
@@ -68,28 +68,6 @@ static __inline__ int br_mac_hash(unsigned char *mac)
...
@@ -68,28 +68,6 @@ static __inline__ int br_mac_hash(unsigned char *mac)
return
x
&
(
BR_HASH_SIZE
-
1
);
return
x
&
(
BR_HASH_SIZE
-
1
);
}
}
static
__inline__
void
__hash_link
(
struct
net_bridge
*
br
,
struct
net_bridge_fdb_entry
*
ent
,
int
hash
)
{
ent
->
next_hash
=
br
->
hash
[
hash
];
if
(
ent
->
next_hash
!=
NULL
)
ent
->
next_hash
->
pprev_hash
=
&
ent
->
next_hash
;
br
->
hash
[
hash
]
=
ent
;
ent
->
pprev_hash
=
&
br
->
hash
[
hash
];
}
static
__inline__
void
__hash_unlink
(
struct
net_bridge_fdb_entry
*
ent
)
{
*
(
ent
->
pprev_hash
)
=
ent
->
next_hash
;
if
(
ent
->
next_hash
!=
NULL
)
ent
->
next_hash
->
pprev_hash
=
ent
->
pprev_hash
;
ent
->
next_hash
=
NULL
;
ent
->
pprev_hash
=
NULL
;
}
void
br_fdb_changeaddr
(
struct
net_bridge_port
*
p
,
unsigned
char
*
newaddr
)
void
br_fdb_changeaddr
(
struct
net_bridge_port
*
p
,
unsigned
char
*
newaddr
)
{
{
struct
net_bridge
*
br
;
struct
net_bridge
*
br
;
...
@@ -99,22 +77,24 @@ void br_fdb_changeaddr(struct net_bridge_port *p, unsigned char *newaddr)
...
@@ -99,22 +77,24 @@ void br_fdb_changeaddr(struct net_bridge_port *p, unsigned char *newaddr)
br
=
p
->
br
;
br
=
p
->
br
;
write_lock_bh
(
&
br
->
hash_lock
);
write_lock_bh
(
&
br
->
hash_lock
);
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
struct
net_bridge_fdb_entry
*
f
;
struct
hlist_node
*
h
;
hlist_for_each
(
h
,
&
br
->
hash
[
i
])
{
struct
net_bridge_fdb_entry
*
f
=
hlist_entry
(
h
,
struct
net_bridge_fdb_entry
,
hlist
);
f
=
br
->
hash
[
i
];
while
(
f
!=
NULL
)
{
if
(
f
->
dst
==
p
&&
f
->
is_local
)
{
if
(
f
->
dst
==
p
&&
f
->
is_local
)
{
memcpy
(
f
->
addr
.
addr
,
newaddr
,
ETH_ALEN
);
memcpy
(
f
->
addr
.
addr
,
newaddr
,
ETH_ALEN
);
if
(
newhash
!=
i
)
{
if
(
newhash
!=
i
)
{
__hash_unlink
(
f
);
hlist_del
(
&
f
->
hlist
);
__hash_link
(
br
,
f
,
newhash
);
hlist_add_head
(
&
f
->
hlist
,
&
br
->
hash
[
newhash
]);
}
}
write_unlock_bh
(
&
br
->
hash_lock
);
goto
out
;
return
;
}
}
f
=
f
->
next_hash
;
}
}
}
}
out:
write_unlock_bh
(
&
br
->
hash_lock
);
write_unlock_bh
(
&
br
->
hash_lock
);
}
}
...
@@ -127,19 +107,16 @@ void br_fdb_cleanup(struct net_bridge *br)
...
@@ -127,19 +107,16 @@ void br_fdb_cleanup(struct net_bridge *br)
write_lock_bh
(
&
br
->
hash_lock
);
write_lock_bh
(
&
br
->
hash_lock
);
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
struct
net_bridge_fdb_entry
*
f
;
struct
hlist_node
*
h
,
*
g
;
f
=
br
->
hash
[
i
];
while
(
f
!=
NULL
)
{
struct
net_bridge_fdb_entry
*
g
;
g
=
f
->
next_hash
;
hlist_for_each_safe
(
h
,
g
,
&
br
->
hash
[
i
])
{
struct
net_bridge_fdb_entry
*
f
=
hlist_entry
(
h
,
struct
net_bridge_fdb_entry
,
hlist
);
if
(
!
f
->
is_static
&&
if
(
!
f
->
is_static
&&
time_before_eq
(
f
->
ageing_timer
,
timeout
))
{
time_before_eq
(
f
->
ageing_timer
,
timeout
))
{
__hash_unlink
(
f
);
hlist_del
(
&
f
->
hlist
);
br_fdb_put
(
f
);
br_fdb_put
(
f
);
}
}
f
=
g
;
}
}
}
}
write_unlock_bh
(
&
br
->
hash_lock
);
write_unlock_bh
(
&
br
->
hash_lock
);
...
@@ -151,18 +128,15 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
...
@@ -151,18 +128,15 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
write_lock_bh
(
&
br
->
hash_lock
);
write_lock_bh
(
&
br
->
hash_lock
);
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
struct
net_bridge_fdb_entry
*
f
;
struct
hlist_node
*
h
,
*
g
;
f
=
br
->
hash
[
i
];
hlist_for_each_safe
(
h
,
g
,
&
br
->
hash
[
i
])
{
while
(
f
!=
NULL
)
{
struct
net_bridge_fdb_entry
*
f
struct
net_bridge_fdb_entry
*
g
;
=
hlist_entry
(
h
,
struct
net_bridge_fdb_entry
,
hlist
);
g
=
f
->
next_hash
;
if
(
f
->
dst
==
p
)
{
if
(
f
->
dst
==
p
)
{
__hash_unlink
(
f
);
hlist_del
(
&
f
->
hlist
);
br_fdb_put
(
f
);
br_fdb_put
(
f
);
}
}
f
=
g
;
}
}
}
}
write_unlock_bh
(
&
br
->
hash_lock
);
write_unlock_bh
(
&
br
->
hash_lock
);
...
@@ -170,25 +144,24 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
...
@@ -170,25 +144,24 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
struct
net_bridge_fdb_entry
*
br_fdb_get
(
struct
net_bridge
*
br
,
unsigned
char
*
addr
)
struct
net_bridge_fdb_entry
*
br_fdb_get
(
struct
net_bridge
*
br
,
unsigned
char
*
addr
)
{
{
struct
net_bridge_fdb_entry
*
fdb
;
struct
hlist_node
*
h
;
read_lock_bh
(
&
br
->
hash_lock
);
read_lock_bh
(
&
br
->
hash_lock
);
fdb
=
br
->
hash
[
br_mac_hash
(
addr
)];
while
(
fdb
!=
NULL
)
{
hlist_for_each
(
h
,
&
br
->
hash
[
br_mac_hash
(
addr
)])
{
struct
net_bridge_fdb_entry
*
fdb
=
hlist_entry
(
h
,
struct
net_bridge_fdb_entry
,
hlist
);
if
(
!
memcmp
(
fdb
->
addr
.
addr
,
addr
,
ETH_ALEN
))
{
if
(
!
memcmp
(
fdb
->
addr
.
addr
,
addr
,
ETH_ALEN
))
{
if
(
!
has_expired
(
br
,
fdb
))
{
if
(
has_expired
(
br
,
fdb
))
goto
ret_null
;
atomic_inc
(
&
fdb
->
use_count
);
atomic_inc
(
&
fdb
->
use_count
);
read_unlock_bh
(
&
br
->
hash_lock
);
read_unlock_bh
(
&
br
->
hash_lock
);
return
fdb
;
return
fdb
;
}
}
read_unlock_bh
(
&
br
->
hash_lock
);
return
NULL
;
}
fdb
=
fdb
->
next_hash
;
}
}
ret_null:
read_unlock_bh
(
&
br
->
hash_lock
);
read_unlock_bh
(
&
br
->
hash_lock
);
return
NULL
;
return
NULL
;
}
}
...
@@ -213,12 +186,16 @@ int br_fdb_get_entries(struct net_bridge *br,
...
@@ -213,12 +186,16 @@ int br_fdb_get_entries(struct net_bridge *br,
read_lock_bh
(
&
br
->
hash_lock
);
read_lock_bh
(
&
br
->
hash_lock
);
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
BR_HASH_SIZE
;
i
++
)
{
struct
net_bridge_fdb_entry
*
f
;
struct
hlist_node
*
h
;
for
(
f
=
br
->
hash
[
i
];
f
!=
NULL
&&
num
<
maxnum
;
hlist_for_each
(
h
,
&
br
->
hash
[
i
])
{
f
=
f
->
next_hash
)
{
struct
net_bridge_fdb_entry
*
f
=
hlist_entry
(
h
,
struct
net_bridge_fdb_entry
,
hlist
);
struct
__fdb_entry
ent
;
struct
__fdb_entry
ent
;
if
(
num
>=
maxnum
)
goto
out
;
if
(
has_expired
(
br
,
f
))
if
(
has_expired
(
br
,
f
))
continue
;
continue
;
...
@@ -277,14 +254,15 @@ void br_fdb_insert(struct net_bridge *br,
...
@@ -277,14 +254,15 @@ void br_fdb_insert(struct net_bridge *br,
unsigned
char
*
addr
,
unsigned
char
*
addr
,
int
is_local
)
int
is_local
)
{
{
struct
hlist_node
*
h
;
struct
net_bridge_fdb_entry
*
fdb
;
struct
net_bridge_fdb_entry
*
fdb
;
int
hash
;
int
hash
;
hash
=
br_mac_hash
(
addr
);
hash
=
br_mac_hash
(
addr
);
write_lock_bh
(
&
br
->
hash_lock
);
write_lock_bh
(
&
br
->
hash_lock
);
fdb
=
br
->
hash
[
hash
];
hlist_for_each
(
h
,
&
br
->
hash
[
hash
])
{
while
(
fdb
!=
NULL
)
{
fdb
=
hlist_entry
(
h
,
struct
net_bridge_fdb_entry
,
hlist
);
if
(
!
fdb
->
is_local
&&
if
(
!
fdb
->
is_local
&&
!
memcmp
(
fdb
->
addr
.
addr
,
addr
,
ETH_ALEN
))
{
!
memcmp
(
fdb
->
addr
.
addr
,
addr
,
ETH_ALEN
))
{
__fdb_possibly_replace
(
fdb
,
source
,
is_local
);
__fdb_possibly_replace
(
fdb
,
source
,
is_local
);
...
@@ -292,7 +270,6 @@ void br_fdb_insert(struct net_bridge *br,
...
@@ -292,7 +270,6 @@ void br_fdb_insert(struct net_bridge *br,
return
;
return
;
}
}
fdb
=
fdb
->
next_hash
;
}
}
fdb
=
kmalloc
(
sizeof
(
*
fdb
),
GFP_ATOMIC
);
fdb
=
kmalloc
(
sizeof
(
*
fdb
),
GFP_ATOMIC
);
...
@@ -308,7 +285,7 @@ void br_fdb_insert(struct net_bridge *br,
...
@@ -308,7 +285,7 @@ void br_fdb_insert(struct net_bridge *br,
fdb
->
is_static
=
is_local
;
fdb
->
is_static
=
is_local
;
fdb
->
ageing_timer
=
jiffies
;
fdb
->
ageing_timer
=
jiffies
;
__hash_link
(
br
,
fdb
,
hash
);
hlist_add_head
(
&
fdb
->
hlist
,
&
br
->
hash
[
hash
]
);
write_unlock_bh
(
&
br
->
hash_lock
);
write_unlock_bh
(
&
br
->
hash_lock
);
}
}
net/bridge/br_private.h
View file @
a8c505ff
...
@@ -43,8 +43,7 @@ struct mac_addr
...
@@ -43,8 +43,7 @@ struct mac_addr
struct
net_bridge_fdb_entry
struct
net_bridge_fdb_entry
{
{
struct
net_bridge_fdb_entry
*
next_hash
;
struct
hlist_node
hlist
;
struct
net_bridge_fdb_entry
**
pprev_hash
;
atomic_t
use_count
;
atomic_t
use_count
;
mac_addr
addr
;
mac_addr
addr
;
struct
net_bridge_port
*
dst
;
struct
net_bridge_port
*
dst
;
...
@@ -86,7 +85,7 @@ struct net_bridge
...
@@ -86,7 +85,7 @@ struct net_bridge
struct
net_device
dev
;
struct
net_device
dev
;
struct
net_device_stats
statistics
;
struct
net_device_stats
statistics
;
rwlock_t
hash_lock
;
rwlock_t
hash_lock
;
struct
net_bridge_fdb_entry
*
hash
[
BR_HASH_SIZE
];
struct
hlist_head
hash
[
BR_HASH_SIZE
];
struct
timer_list
tick
;
struct
timer_list
tick
;
/* STP */
/* STP */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment