Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
BIRD Internet Routing Daemon
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
labs
BIRD Internet Routing Daemon
Commits
a7a7372a
Commit
a7a7372a
authored
Jul 18, 2014
by
Ondřej Zajíček
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Temporary integrated OSPF commit.
parent
70945cb6
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
781 additions
and
693 deletions
+781
-693
nest/locks.c
nest/locks.c
+6
-4
nest/locks.h
nest/locks.h
+3
-2
proto/ospf/dbdes.c
proto/ospf/dbdes.c
+8
-11
proto/ospf/hello.c
proto/ospf/hello.c
+1
-1
proto/ospf/iface.c
proto/ospf/iface.c
+5
-12
proto/ospf/lsack.c
proto/ospf/lsack.c
+3
-7
proto/ospf/lsreq.c
proto/ospf/lsreq.c
+2
-1
proto/ospf/lsupd.c
proto/ospf/lsupd.c
+57
-31
proto/ospf/neighbor.c
proto/ospf/neighbor.c
+42
-17
proto/ospf/ospf.c
proto/ospf/ospf.c
+80
-90
proto/ospf/ospf.h
proto/ospf/ospf.h
+272
-261
proto/ospf/rt.c
proto/ospf/rt.c
+19
-24
proto/ospf/rt.h
proto/ospf/rt.h
+30
-27
proto/ospf/topology.c
proto/ospf/topology.c
+143
-197
proto/ospf/topology.h
proto/ospf/topology.h
+110
-8
No files found.
nest/locks.c
View file @
a7a7372a
...
...
@@ -22,10 +22,11 @@
* or some other non-shareable resource, it asks the core to lock it and it doesn't
* use the resource until it's notified that it has acquired the lock.
*
* Object locks are represented by &object_lock structures which are in turn a
kind of
* resource. Lockable resources are uniquely determined by resource type
* Object locks are represented by &object_lock structures which are in turn a
*
kind of
resource. Lockable resources are uniquely determined by resource type
* (%OBJLOCK_UDP for a UDP port etc.), IP address (usually a broadcast or
* multicast address the port is bound to), port number and interface.
* multicast address the port is bound to), port number, interface and optional
* instance ID.
*/
#undef LOCAL_DEBUG
...
...
@@ -45,6 +46,7 @@ olock_same(struct object_lock *x, struct object_lock *y)
x
->
type
==
y
->
type
&&
x
->
iface
==
y
->
iface
&&
x
->
port
==
y
->
port
&&
x
->
inst
==
y
->
inst
&&
ipa_equal
(
x
->
addr
,
y
->
addr
);
}
...
...
@@ -88,7 +90,7 @@ olock_dump(resource *r)
struct
object_lock
*
l
=
(
struct
object_lock
*
)
r
;
static
char
*
olock_states
[]
=
{
"free"
,
"locked"
,
"waiting"
,
"event"
};
debug
(
"(%d:%s:%I:%d
) [%s]
\n
"
,
l
->
type
,
(
l
->
iface
?
l
->
iface
->
name
:
"?"
),
l
->
addr
,
l
->
por
t
,
olock_states
[
l
->
state
]);
debug
(
"(%d:%s:%I:%d
:%d) [%s]
\n
"
,
l
->
type
,
(
l
->
iface
?
l
->
iface
->
name
:
"?"
),
l
->
addr
,
l
->
port
,
l
->
ins
t
,
olock_states
[
l
->
state
]);
if
(
!
EMPTY_LIST
(
l
->
waiters
))
debug
(
" [wanted]
\n
"
);
}
...
...
nest/locks.h
View file @
a7a7372a
...
...
@@ -26,9 +26,10 @@
struct
object_lock
{
resource
r
;
ip_addr
addr
;
/* Identification of a object: IP address */
unsigned
int
type
;
/* ... object type (OBJLOCK_xxx) */
uint
type
;
/* ... object type (OBJLOCK_xxx) */
uint
port
;
/* ... port number */
uint
inst
;
/* ... instance ID */
struct
iface
*
iface
;
/* ... interface */
unsigned
int
port
;
/* ... port number */
void
(
*
hook
)(
struct
object_lock
*
);
/* Called when the lock succeeds */
void
*
data
;
/* User data */
/* ... internal to lock manager, don't touch ... */
...
...
proto/ospf/dbdes.c
View file @
a7a7372a
...
...
@@ -200,15 +200,11 @@ ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
* of the buffer.
*/
void
ospf_send_dbdes
(
struct
ospf_neighbor
*
n
,
int
next
)
ospf_send_dbdes
(
struct
ospf_
proto
*
p
,
struct
ospf_
neighbor
*
n
,
int
next
)
{
struct
ospf_iface
*
ifa
=
n
->
ifa
;
struct
ospf_area
*
oa
=
ifa
->
oa
;
struct
ospf_proto
*
p
=
oa
->
po
;
/* RFC 2328 10.8 */
if
(
oa
->
rt
==
NULL
)
if
(
n
->
ifa
->
oa
->
rt
==
NULL
)
return
;
switch
(
n
->
state
)
...
...
@@ -312,6 +308,7 @@ ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_ne
s_add_tail
(
&
n
->
lsrql
,
SNODE
req
);
req
->
lsa
=
lsa
;
req
->
lsa_body
=
LSA_BODY_DUMMY
;
}
}
...
...
@@ -394,7 +391,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
n
->
imms
=
rcv_imms
;
OSPF_TRACE
(
D_PACKETS
,
"I'm slave to %I"
,
n
->
ip
);
ospf_neigh_sm
(
n
,
INM_NEGDONE
);
ospf_send_dbdes
(
n
,
1
);
ospf_send_dbdes
(
p
,
n
,
1
);
break
;
}
...
...
@@ -426,7 +423,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if
(
!
(
n
->
myimms
&
DBDES_MS
))
{
/* Slave should retransmit dbdes packet */
ospf_send_dbdes
(
n
,
0
);
ospf_send_dbdes
(
p
,
n
,
0
);
}
return
;
}
...
...
@@ -472,7 +469,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if
(
!
(
n
->
myimms
&
DBDES_M
)
&&
!
(
n
->
imms
&
DBDES_M
))
ospf_neigh_sm
(
n
,
INM_EXDONE
);
else
ospf_send_dbdes
(
n
,
1
);
ospf_send_dbdes
(
p
,
n
,
1
);
}
else
{
...
...
@@ -489,7 +486,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if
(
ospf_process_dbdes
(
p
,
pkt
,
n
)
<
0
)
return
;
ospf_send_dbdes
(
n
,
1
);
ospf_send_dbdes
(
p
,
n
,
1
);
}
break
;
...
...
@@ -504,7 +501,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if
(
!
(
n
->
myimms
&
DBDES_MS
))
{
/* Slave should retransmit dbdes packet */
ospf_send_dbdes
(
n
,
0
);
ospf_send_dbdes
(
p
,
n
,
0
);
}
return
;
}
...
...
proto/ospf/hello.c
View file @
a7a7372a
...
...
@@ -275,7 +275,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* Check consistency of existing neighbor entry */
if
(
n
)
{
u
nsigned
t
=
ifa
->
type
;
u
int
t
=
ifa
->
type
;
if
(
ospf_is_v2
(
p
)
&&
((
t
==
OSPF_IT_BCAST
)
||
(
t
==
OSPF_IT_NBMA
)
||
(
t
==
OSPF_IT_PTMP
)))
{
/* Neighbor identified by IP address; Router ID may change */
...
...
proto/ospf/iface.c
View file @
a7a7372a
...
...
@@ -620,18 +620,11 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
add_tail
(
&
oa
->
po
->
iface_list
,
NODE
ifa
);
/*
* In some cases we allow more ospf_ifaces on one physical iface.
* In OSPFv2, if they use different IP address prefix.
* In OSPFv3, if they use different instance_id.
* Therefore, we store such info to lock->addr field.
*/
// XXXX review
struct
object_lock
*
lock
=
olock_new
(
pool
);
lock
->
addr
=
ospf_is_v2
(
p
)
?
ifa
->
addr
->
prefix
:
_MI6
(
0
,
0
,
0
,
ifa
->
instance_id
)
;
lock
->
addr
=
ospf_is_v2
(
p
)
?
ifa
->
addr
->
prefix
:
IPA_NONE
;
lock
->
type
=
OBJLOCK_IP
;
lock
->
port
=
OSPF_PROTO
;
lock
->
inst
=
ifa
->
instance_id
;
lock
->
iface
=
iface
;
lock
->
data
=
ifa
;
lock
->
hook
=
ospf_iface_add
;
...
...
@@ -997,7 +990,7 @@ ospf_walk_matching_iface_patts(struct ospf_proto *p, struct ospf_mip_walk *s)
BIT32_SET
(
s
->
ignore
,
id
);
/* If we already found it in previous areas, ignore it and add warning */
if
(
!
BIT32_TEST
(
s
->
active
,
id
))
if
(
BIT32_TEST
(
s
->
active
,
id
))
{
s
->
warn
=
1
;
continue
;
}
BIT32_SET
(
s
->
active
,
id
);
...
...
@@ -1046,7 +1039,7 @@ ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a)
{
struct
ospf_mip_walk
s
=
{
.
iface
=
a
->
iface
,
.
a
=
a
};
while
(
ospf_walk_matching_iface_patts
(
p
,
&
s
))
ospf_iface_new
(
s
.
oa
,
s
.
a
,
s
.
ip
);
ospf_iface_new
(
s
.
oa
,
a
,
s
.
ip
);
}
if
(
flags
&
IF_CHANGE_DOWN
)
...
...
@@ -1078,7 +1071,7 @@ ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a)
{
struct
ospf_mip_walk
s
=
{
.
iface
=
a
->
iface
};
while
(
ospf_walk_matching_iface_patts
(
p
,
&
s
))
ospf_iface_new
(
s
.
oa
,
s
.
a
,
s
.
ip
);
ospf_iface_new
(
s
.
oa
,
a
,
s
.
ip
);
}
if
(
flags
&
IF_CHANGE_DOWN
)
...
...
proto/ospf/lsack.c
View file @
a7a7372a
...
...
@@ -79,10 +79,9 @@ ospf_reset_lsack_queue(struct ospf_neighbor *n)
}
static
inline
void
ospf_send_lsack
(
struct
ospf_neighbor
*
n
,
int
queue
)
ospf_send_lsack
_
(
struct
ospf_proto
*
p
,
struct
ospf_neighbor
*
n
,
int
queue
)
{
struct
ospf_iface
*
ifa
=
n
->
ifa
;
struct
ospf_proto
*
p
=
ifa
->
oa
->
po
;
struct
ospf_lsa_header
*
lsas
;
struct
ospf_packet
*
pkt
;
struct
lsa_node
*
no
;
...
...
@@ -121,10 +120,10 @@ ospf_send_lsack(struct ospf_neighbor *n, int queue)
}
void
ospf_
lsack_send
(
struct
ospf_neighbor
*
n
,
int
queue
)
ospf_
send_lsack
(
struct
ospf_proto
*
p
,
struct
ospf_neighbor
*
n
,
int
queue
)
{
while
(
!
EMPTY_LIST
(
n
->
ackl
[
queue
]))
ospf_send_lsack
(
n
,
queue
);
ospf_send_lsack
_
(
p
,
n
,
queue
);
}
void
...
...
@@ -160,9 +159,6 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
if
(
lsa_comp
(
&
lsa
,
&
ret
->
lsa
)
!=
CMP_SAME
)
{
if
((
lsa
.
sn
==
LSA_MAXSEQNO
)
&&
(
lsa
.
age
==
LSA_MAXAGE
))
continue
;
OSPF_TRACE
(
D_PACKETS
,
"Strange LSACK from %I"
,
n
->
ip
);
OSPF_TRACE
(
D_PACKETS
,
"Type: %04x, Id: %R, Rt: %R"
,
lsa_type
,
lsa
.
id
,
lsa
.
rt
);
...
...
proto/ospf/lsreq.c
View file @
a7a7372a
...
...
@@ -71,7 +71,8 @@ ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n)
ospf_pkt_fill_hdr
(
ifa
,
pkt
,
LSREQ_P
);
ospf_lsreq_body
(
p
,
pkt
,
&
lsrs
,
&
lsr_max
);
// for (i = 0; i < lsr_max; i++)
/* We send smaller LSREQ to prevent multiple LSACKs as answer */
lsr_max
=
lsr_max
/
4
;
i
=
0
;
WALK_SLIST
(
en
,
n
->
lsrql
)
...
...
proto/ospf/lsupd.c
View file @
a7a7372a
...
...
@@ -115,7 +115,8 @@ ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n)
s_add_tail
(
&
n
->
lsrtl
,
SNODE
ret
);
}
memcpy
(
&
ret
->
lsa
,
&
en
->
lsa
,
sizeof
(
struct
ospf_lsa_header
));
ret
->
lsa
=
en
->
lsa
;
ret
->
lsa_body
=
LSA_BODY_DUMMY
;
}
static
inline
int
...
...
@@ -134,25 +135,37 @@ ospf_lsa_lsrt_down(struct top_hash_entry *en, struct ospf_neighbor *n)
return
0
;
}
void
ospf_add_flushed_to_lsrt
(
struct
ospf_proto
*
p
,
struct
ospf_neighbor
*
n
)
{
struct
top_hash_entry
*
en
;
WALK_SLIST
(
en
,
p
->
lsal
)
if
((
en
->
lsa
.
age
==
LSA_MAXAGE
)
&&
(
en
->
lsa_body
!=
NULL
)
&&
lsa_flooding_allowed
(
en
->
lsa_type
,
en
->
domain
,
n
->
ifa
))
ospf_lsa_lsrt_up
(
en
,
n
);
}
static
void
ospf_
lsupd_flood_ifa
(
struct
ospf_proto
*
p
,
struct
ospf_iface
*
ifa
,
struct
top_hash_entry
*
en
);
static
void
ospf_
send_lsupd_to_ifa
(
struct
ospf_proto
*
p
,
struct
top_hash_entry
*
en
,
struct
ospf_iface
*
ifa
);
/**
* ospf_
lsupd_flood - send received or generate
d LSA to the neighbors
* @p: OSPF protocol
* ospf_
flood_lsa - sen
d LSA to the neighbors
* @p: OSPF protocol
instance
* @en: LSA entry
* @from: neighbor than sent this LSA (or NULL if LSA is local)
*
* return value - was the LSA flooded back?
*/
int
ospf_
lsupd_flood
(
struct
ospf_proto
*
p
,
struct
top_hash_entry
*
en
,
struct
ospf_neighbor
*
from
)
ospf_
flood_lsa
(
struct
ospf_proto
*
p
,
struct
top_hash_entry
*
en
,
struct
ospf_neighbor
*
from
)
{
struct
ospf_iface
*
ifa
;
struct
ospf_neighbor
*
n
;
/* RFC 2328 13.3 */
int
back
=
0
;
WALK_LIST
(
ifa
,
p
->
iface_list
)
{
...
...
@@ -185,6 +198,8 @@ ospf_lsupd_flood(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_ne
{
s_rem_node
(
SNODE
req
);
ospf_hash_delete
(
n
->
lsrqh
,
req
);
n
->
want_lsreq
=
1
;
if
((
EMPTY_SLIST
(
n
->
lsrql
))
&&
(
n
->
state
==
NEIGHBOR_LOADING
))
ospf_neigh_sm
(
n
,
INM_LOADDONE
);
}
...
...
@@ -227,7 +242,7 @@ ospf_lsupd_flood(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_ne
}
/* 13.3 (5) - finally flood the packet */
ospf_
lsupd_flood_ifa
(
p
,
ifa
,
en
);
ospf_
send_lsupd_to_ifa
(
p
,
en
,
ifa
);
}
return
back
;
...
...
@@ -288,7 +303,7 @@ ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
static
void
ospf_
lsupd_flood_ifa
(
struct
ospf_proto
*
p
,
struct
ospf_iface
*
ifa
,
struct
top_hash_entry
*
en
)
ospf_
send_lsupd_to_ifa
(
struct
ospf_proto
*
p
,
struct
top_hash_entry
*
en
,
struct
ospf_iface
*
ifa
)
{
uint
c
=
ospf_prepare_lsupd
(
p
,
ifa
,
&
en
,
1
);
...
...
@@ -384,7 +399,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* RFC 2328 13. */
int
sendreq
=
1
;
/* XXXX: review sendreq */
int
skip_lsreq
=
0
;
n
->
want_lsreq
=
0
;
uint
plen
=
ntohs
(
pkt
->
length
);
if
(
plen
<
(
ospf_lsupd_hdrlen
(
p
)
+
sizeof
(
struct
ospf_lsa_header
)))
...
...
@@ -436,7 +452,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
u16
chsum
=
lsa_n
->
checksum
;
if
(
chsum
!=
lsasum_check
(
lsa_n
,
NULL
))
{
log
(
L_WARN
"%s: Received LSA from %I with bad chec
sk
um: %x %x"
,
log
(
L_WARN
"%s: Received LSA from %I with bad chec
ks
um: %x %x"
,
p
->
p
.
name
,
n
->
ip
,
chsum
,
lsa_n
->
checksum
);
continue
;
}
...
...
@@ -501,7 +517,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
if
(
en
&&
((
now
-
en
->
inst_time
)
<
MINLSARRIVAL
))
{
OSPF_TRACE
(
D_EVENTS
,
"Skipping LSA received in less that MinLSArrival"
);
s
endreq
=
0
;
s
kip_lsreq
=
1
;
continue
;
}
...
...
@@ -514,7 +530,6 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
{
log
(
L_WARN
"%s: Received invalid LSA from %I"
,
p
->
p
.
name
,
n
->
ip
);
mb_free
(
body
);
sendreq
=
0
;
continue
;
}
...
...
@@ -528,22 +543,27 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
}
/* 13. (5c) - remove old LSA from all retransmission lists */
/* Must be done before (5b), otherwise it also removes the new entries from (5b) */
/*
* We only need to remove it from the retransmission list of the neighbor
* that send us the new LSA. The old LSA is automatically replaced in
* retransmission lists by the new LSA.
*/
if
(
en
)
ospf_lsa_lsrt_down
(
en
,
n
);
#if 0
/*
{
struct ospf_iface *ifi;
struct ospf_neighbor *ni;
WALK_LIST(ifi, p->iface_list)
WALK_LIST(ni, ifi->neigh_list)
if (ni->state > NEIGHBOR_EXSTART)
ospf_lsa_lsrt_down(en, ni);
}
*/
* Old code for removing LSA from all retransmission lists. Must be done
* before (5b), otherwise it also removes the new entries from (5b).
*/
struct ospf_iface *ifi;
struct ospf_neighbor *ni;
WALK_LIST(ifi, p->iface_list)
WALK_LIST(ni, ifi->neigh_list)
if (ni->state > NEIGHBOR_EXSTART)
ospf_lsa_lsrt_down(en, ni);
#endif
/* 13. (5d) - install new LSA into database */
en
=
ospf_install_lsa
(
p
,
&
lsa
,
lsa_type
,
lsa_domain
,
body
);
...
...
@@ -553,7 +573,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
ospf_notify_net_lsa
(
ifa
);
/* 13. (5b) - flood new LSA */
int
flood_back
=
ospf_
lsupd_flood
(
p
,
en
,
n
);
int
flood_back
=
ospf_
flood_lsa
(
p
,
en
,
n
);
/* 13.5. - schedule ACKs (tbl 19, cases 1+2) */
if
(
!
flood_back
)
...
...
@@ -582,7 +602,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
else
ospf_enqueue_lsack
(
n
,
lsa_n
,
ACKL_DIRECT
);
s
endreq
=
0
;
s
kip_lsreq
=
1
;
continue
;
}
...
...
@@ -598,11 +618,17 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
}
}
/* Send direct LSAs */
ospf_lsack_send
(
n
,
ACKL_DIRECT
);
/* If loading, ask for another part of neighbor's database */
if
(
sendreq
&&
(
n
->
state
==
NEIGHBOR_LOADING
))
/* Send direct LSACKs */
ospf_send_lsack
(
p
,
n
,
ACKL_DIRECT
);
/*
* In loading state, we should ask for another batch of LSAs. This is only
* vaguely mentioned in RFC 2328. We send a new LSREQ only if the current
* LSUPD actually removed some entries from LSA request list (want_lsreq) and
* did not contain duplicate or early LSAs (skip_lsreq). The first condition
* prevents endless floods, the second condition helps with flow control.
*/
if
((
n
->
state
==
NEIGHBOR_LOADING
)
&&
n
->
want_lsreq
&&
!
skip_lsreq
)
ospf_send_lsreq
(
p
,
n
);
}
proto/ospf/neighbor.c
View file @
a7a7372a
...
...
@@ -33,13 +33,26 @@ static void rxmt_timer_hook(timer * timer);
static
void
ackd_timer_hook
(
timer
*
t
);
static
void
init_lists
(
struct
ospf_neighbor
*
n
)
init_lists
(
struct
ospf_
proto
*
p
,
struct
ospf_
neighbor
*
n
)
{
s_init_list
(
&
(
n
->
lsrql
));
n
->
lsrqh
=
ospf_top_new
(
n
->
pool
);
n
->
lsrqh
=
ospf_top_new
(
p
,
n
->
pool
);
s_init_list
(
&
(
n
->
lsrtl
));
n
->
lsrth
=
ospf_top_new
(
n
->
pool
);
n
->
lsrth
=
ospf_top_new
(
p
,
n
->
pool
);
}
static
void
release_lsrtl
(
struct
ospf_proto
*
p
,
struct
ospf_neighbor
*
n
)
{
struct
top_hash_entry
*
ret
,
*
en
;
WALK_SLIST
(
ret
,
n
->
lsrtl
)
{
en
=
ospf_hash_find_entry
(
p
->
gr
,
ret
);
if
(
en
)
en
->
ret_count
--
;
}
}
/* Resets LSA request and retransmit lists.
...
...
@@ -47,11 +60,12 @@ init_lists(struct ospf_neighbor *n)
* it is reset during entering EXCHANGE state.
*/
static
void
reset_lists
(
struct
ospf_neighbor
*
n
)
reset_lists
(
struct
ospf_
proto
*
p
,
struct
ospf_
neighbor
*
n
)
{
release_lsrtl
(
p
,
n
);
ospf_top_free
(
n
->
lsrqh
);
ospf_top_free
(
n
->
lsrth
);
init_lists
(
n
);
init_lists
(
p
,
n
);
}
struct
ospf_neighbor
*
...
...
@@ -68,7 +82,7 @@ ospf_neighbor_new(struct ospf_iface *ifa)
n
->
csn
=
0
;
n
->
state
=
NEIGHBOR_DOWN
;
init_lists
(
n
);
init_lists
(
p
,
n
);
s_init
(
&
(
n
->
dbsi
),
&
(
p
->
lsal
));
n
->
inactim
=
tm_new
(
pool
);
...
...
@@ -360,6 +374,10 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
s_get
(
&
(
n
->
dbsi
));
s_init
(
&
(
n
->
dbsi
),
&
p
->
lsal
);
/* Add MaxAge LSA entries to retransmission list */
ospf_add_flushed_to_lsrt
(
p
,
n
);
/* FIXME: Why is this here ? */
ospf_reset_lsack_queue
(
n
);
}
else
...
...
@@ -388,7 +406,7 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
if
(
n
->
state
>=
NEIGHBOR_EXSTART
)
if
(
!
can_do_adj
(
n
))
{
reset_lists
(
n
);
reset_lists
(
p
,
n
);
neigh_chstate
(
n
,
NEIGHBOR_2WAY
);
}
break
;
...
...
@@ -399,7 +417,7 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
case
INM_BADLSREQ
:
if
(
n
->
state
>=
NEIGHBOR_EXCHANGE
)
{
reset_lists
(
n
);
reset_lists
(
p
,
n
);
neigh_chstate
(
n
,
NEIGHBOR_EXSTART
);
}
break
;
...
...
@@ -407,12 +425,12 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
case
INM_KILLNBR
:
case
INM_LLDOWN
:
case
INM_INACTTIM
:
reset_lists
(
n
);
reset_lists
(
p
,
n
);
neigh_chstate
(
n
,
NEIGHBOR_DOWN
);
break
;
case
INM_1WAYREC
:
reset_lists
(
n
);
reset_lists
(
p
,
n
);
neigh_chstate
(
n
,
NEIGHBOR_INIT
);
break
;
...
...
@@ -552,8 +570,10 @@ ospf_neigh_remove(struct ospf_neighbor *n)
nn
->
found
=
0
;
}
s_get
(
&
(
n
->
dbsi
));
neigh_chstate
(
n
,
NEIGHBOR_DOWN
);
s_get
(
&
(
n
->
dbsi
));
release_lsrtl
(
p
,
n
);
rem_node
(
NODE
n
);
rfree
(
n
->
pool
);
OSPF_TRACE
(
D_EVENTS
,
"Deleting neigbor %R"
,
n
->
rid
);
...
...
@@ -620,9 +640,9 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
}
static
void
rxmt_timer_hook
(
timer
*
timer
)
rxmt_timer_hook
(
timer
*
t
)
{
struct
ospf_neighbor
*
n
=
(
struct
ospf_neighbor
*
)
timer
->
data
;
struct
ospf_neighbor
*
n
=
t
->
data
;
struct
ospf_proto
*
p
=
n
->
ifa
->
oa
->
po
;
DBG
(
"%s: RXMT timer fired on interface %s for neigh %I
\n
"
,
...
...
@@ -631,12 +651,12 @@ rxmt_timer_hook(timer * timer)
switch
(
n
->
state
)
{
case
NEIGHBOR_EXSTART
:
ospf_send_dbdes
(
n
,
1
);
ospf_send_dbdes
(
p
,
n
,
1
);
return
;
case
NEIGHBOR_EXCHANGE
:
if
(
n
->
myimms
&
DBDES_MS
)
ospf_send_dbdes
(
n
,
0
);
ospf_send_dbdes
(
p
,
n
,
0
);
case
NEIGHBOR_LOADING
:
ospf_send_lsreq
(
p
,
n
);
return
;
...
...
@@ -653,8 +673,13 @@ rxmt_timer_hook(timer * timer)
}
static
void
ackd_timer_hook
(
timer
*
t
)
ackd_timer_hook
(
timer
*
t
)
{
struct
ospf_neighbor
*
n
=
t
->
data
;
ospf_lsack_send
(
n
,
ACKL_DELAY
);
struct
ospf_proto
*
p
=
n
->
ifa
->
oa
->
po
;
DBG
(
"%s: ACKD timer fired on interface %s for neigh %I
\n
"
,
p
->
p
.
name
,
n
->
ifa
->
ifname
,
n
->
ip
);
ospf_send_lsack
(
p
,
n
,
ACKL_DELAY
);
}
proto/ospf/ospf.c
View file @
a7a7372a
...
...
@@ -11,93 +11,81 @@
/**
* DOC: Open Shortest Path First (OSPF)
*
* The OSPF protocol is quite complicated and its complex implemenation is
* split to many files. In |ospf.c|, you will find mainly the interface
* for communication with the core (e.g., reconfiguration hooks, shutdown
* and initialisation and so on). In |packet.c|, you will find various
* functions for sending and receiving generic OSPF packets. There are
* also routines for authentication and checksumming. File |iface.c| contains
* the interface state machine and functions for allocation and deallocation of OSPF's
* interface data structures. Source |neighbor.c| includes the neighbor state
* machine and functions for election of Designated Router and Backup
* Designated router. In |hello.c|, there are routines for sending
* and receiving of hello packets as well as functions for maintaining
* wait times and the inactivity timer. Files |lsreq.c|, |lsack.c|, |dbdes.c|
* contain functions for sending and receiving of link-state requests,
* link-state acknowledgements and database descriptions respectively.
* In |lsupd.c|, there are functions for sending and receiving
* of link-state updates and also the flooding algorithm. Source |topology.c| is
* a place where routines for searching LSAs in the link-state database,
* adding and deleting them reside, there also are functions for originating
* of various types of LSAs (router LSA, net LSA, external LSA). File |rt.c|
* contains routines for calculating the routing table. |lsalib.c| is a set
* of various functions for working with the LSAs (endianity conversions,
* calculation of checksum etc.).
* The OSPF protocol is quite complicated and its complex implemenation is split
* to many files. In |ospf.c|, you will find mainly the interface for
* communication with the core (e.g., reconfiguration hooks, shutdown and
* initialisation and so on). File |iface.c| contains the interface state
* machine and functions for allocation and deallocation of OSPF's interface
* data structures. Source |neighbor.c| includes the neighbor state machine and
* functions for election of Designated Router and Backup Designated router. In
* |packet.c|, you will find various functions for sending and receiving generic
* OSPF packets. There are also routines for authentication and checksumming.
* In |hello.c|, there are routines for sending and receiving of hello packets
* as well as functions for maintaining wait times and the inactivity timer.
* Files |lsreq.c|, |lsack.c|, |dbdes.c| contain functions for sending and
* receiving of link-state requests, link-state acknowledgements and database
* descriptions respectively. In |lsupd.c|, there are functions for sending and
* receiving of link-state updates and also the flooding algorithm. Source
* |topology.c| is a place where routines for searching LSAs in the link-state
* database, adding and deleting them reside, there also are functions for
* originating of various types of LSAs (router LSA, net LSA, external LSA).
* File |rt.c| contains routines for calculating the routing table. |lsalib.c|
* is a set of various functions for working with the LSAs (endianity
* conversions, calculation of checksum etc.).
*
* One instance of the protocol is able to hold LSA databases for
* multiple OSPF areas, to exchange routing information between
* multiple neighbors and to calculate the routing tables. The core
* structure is &ospf_proto to which multiple &ospf_area and
* &ospf_iface structures are connected. &ospf_area is also connected to
* &top_hash_graph which is a dynamic hashing structure that
* describes the link-state database. It allows fast search, addition
* and deletion. Each LSA is kept in two pieces: header and body. Both of them are
* One instance of the protocol is able to hold LSA databases for multiple OSPF
* areas, to exchange routing information between multiple neighbors and to
* calculate the routing tables. The core structure is &ospf_proto to which
* multiple &ospf_area and &ospf_iface structures are connected. &ospf_proto is
* also connected to &top_hash_graph which is a dynamic hashing structure that
* describes the link-state database. It allows fast search, addition and
* deletion. Each LSA is kept in two pieces: header and body. Both of them are
* kept in the endianity of the CPU.
*
* In OSPFv2 specification, it is implied that there is one IP prefix
* for each physical network/interface (unless it is an ptp link). But
* in modern systems, there might be more independent IP prefixes
* associated with an interface. To handle this situation, we have
* one &ospf_iface for each active IP prefix (instead for each active
* iface); This behaves like virtual interface for the purpose of OSPF.
* If we receive packet, we associate it with a proper virtual interface
* mainly according to its source address.
* In OSPFv2 specification, it is implied that there is one IP prefix for each
* physical network/interface (unless it is an ptp link). But in modern systems,
* there might be more independent IP prefixes associated with an interface. To
* handle this situation, we have one &ospf_iface for each active IP prefix
* (instead for each active iface); This behaves like virtual interface for the
* purpose of OSPF. If we receive packet, we associate it with a proper virtual
* interface mainly according to its source address.
*
* OSPF keeps one socket per &ospf_iface. This allows us (compared to
* one socket approach) to evade problems with a limit of multicast
* groups per socket and with sending multicast packets to appropriate
* interface in a portable way. The socket is associated with
* underlying physical iface and should not receive packets received
* on other ifaces (unfortunately, this is not true on
* BSD). Generally, one packet can be received by more sockets (for
* example, if there are more &ospf_iface on one physical iface),
* therefore we explicitly filter received packets according to
* src/dst IP address and received iface.
* OSPF keeps one socket per &ospf_iface. This allows us (compared to one socket
* approach) to evade problems with a limit of multicast groups per socket and
* with sending multicast packets to appropriate interface in a portable way.
* The socket is associated with underlying physical iface and should not
* receive packets received on other ifaces (unfortunately, this is not true on