Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
babeld
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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
babeld
Commits
210b379a
Commit
210b379a
authored
Aug 07, 2011
by
Juliusz Chroboczek
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'babelz'
parents
c1f87660
da82470c
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
457 additions
and
46 deletions
+457
-46
babeld.c
babeld.c
+38
-4
babeld.man
babeld.man
+35
-0
configuration.c
configuration.c
+28
-0
kernel.h
kernel.h
+1
-0
kernel_netlink.c
kernel_netlink.c
+75
-0
kernel_socket.c
kernel_socket.c
+7
-0
message.c
message.c
+137
-14
network.c
network.c
+34
-1
network.h
network.h
+9
-0
route.c
route.c
+62
-20
route.h
route.h
+31
-7
No files found.
babeld.c
View file @
210b379a
...
...
@@ -125,7 +125,7 @@ main(int argc, char **argv)
protocol_port
=
6697
;
while
(
1
)
{
opt
=
getopt
(
argc
,
argv
,
"m:p:h:H:i:k:A:PsuS:d:g:lwt:T:c:C:DL:I:"
);
opt
=
getopt
(
argc
,
argv
,
"m:p:h:H:i:k:A:PsuS:d:g:lw
z:
t:T:c:C:DL:I:"
);
if
(
opt
<
0
)
break
;
...
...
@@ -202,6 +202,18 @@ main(int argc, char **argv)
case
'w'
:
all_wireless
=
1
;
break
;
case
'z'
:
{
char
*
comma
=
strchr
(
optarg
,
','
);
diversity_kind
=
atoi
(
optarg
);
if
(
comma
==
NULL
)
diversity_factor
=
128
;
else
diversity_factor
=
atoi
(
comma
+
1
);
if
(
diversity_factor
<=
0
||
diversity_factor
>
256
)
goto
usage
;
}
break
;
case
't'
:
export_table
=
atoi
(
optarg
);
if
(
export_table
<
0
||
export_table
>
0xFFFF
)
...
...
@@ -777,7 +789,7 @@ main(int argc, char **argv)
"Syntax: %s "
"[-m multicast_address] [-p port] [-S state-file]
\n
"
" "
"[-h hello] [-H wired_hello] [-i idle_hello]
\n
"
"[-h hello] [-H wired_hello] [-i idle_hello]
[-z kind[,factor]]
\n
"
" "
"[-k metric] [-A metric] [-s] [-P] [-l] [-w] [-u] [-g port]
\n
"
" "
...
...
@@ -922,12 +934,13 @@ dump_tables(FILE *out)
fprintf
(
out
,
"My id %s seqno %d
\n
"
,
format_eui64
(
myid
),
myseqno
);
FOR_ALL_NEIGHBOURS
(
neigh
)
{
fprintf
(
out
,
"Neighbour %s dev %s reach %04x rxcost %d txcost %d%s.
\n
"
,
fprintf
(
out
,
"Neighbour %s dev %s reach %04x rxcost %d txcost %d
chan %d
%s.
\n
"
,
format_address
(
neigh
->
address
),
neigh
->
network
->
ifname
,
neigh
->
reach
,
neighbour_rxcost
(
neigh
),
neigh
->
txcost
,
neigh
->
network
->
channel
,
net_up
(
neigh
->
network
)
?
""
:
" (down)"
);
}
for
(
i
=
0
;
i
<
numxroutes
;
i
++
)
{
...
...
@@ -939,12 +952,33 @@ dump_tables(FILE *out)
const
unsigned
char
*
nexthop
=
memcmp
(
routes
[
i
].
nexthop
,
routes
[
i
].
neigh
->
address
,
16
)
==
0
?
NULL
:
routes
[
i
].
nexthop
;
fprintf
(
out
,
"%s metric %d refmetric %d id %s seqno %d age %d "
char
channels
[
100
];
if
(
routes
[
i
].
channels
[
0
]
==
0
)
channels
[
0
]
=
'\0'
;
else
{
int
k
,
j
=
0
;
snprintf
(
channels
,
100
,
" chan ("
);
j
=
strlen
(
channels
);
for
(
k
=
0
;
k
<
DIVERSITY_HOPS
;
k
++
)
{
if
(
routes
[
i
].
channels
[
k
]
==
0
)
break
;
if
(
k
>
0
)
channels
[
j
++
]
=
','
;
snprintf
(
channels
+
j
,
100
-
j
,
"%d"
,
routes
[
i
].
channels
[
k
]);
j
=
strlen
(
channels
);
}
snprintf
(
channels
+
j
,
100
-
j
,
")"
);
if
(
k
==
0
)
channels
[
0
]
=
'\0'
;
}
fprintf
(
out
,
"%s metric %d refmetric %d id %s seqno %d%s age %d "
"via %s neigh %s%s%s%s
\n
"
,
format_prefix
(
routes
[
i
].
src
->
prefix
,
routes
[
i
].
src
->
plen
),
route_metric
(
&
routes
[
i
]),
routes
[
i
].
refmetric
,
format_eui64
(
routes
[
i
].
src
->
id
),
(
int
)
routes
[
i
].
seqno
,
channels
,
(
int
)(
now
.
tv_sec
-
routes
[
i
].
time
),
routes
[
i
].
neigh
->
network
->
ifname
,
format_address
(
routes
[
i
].
neigh
->
address
),
...
...
babeld.man
View file @
210b379a
...
...
@@ -51,6 +51,24 @@ at which scheduled hello packets are sent on idle interfaces. This
functionality is experimental, don't use it unless you know what you are
doing.
.TP
.BI \-z " kind" " \fR[\fB," factor "\fR]"
Enable diversity-sensitive routing. The value
.B kind
defines the diversity algorithm used, and can be one of
.B 0
(no diversity),
.B 1
(per-interface diversity with no memory),
.B 2
(per-channel diversity with no memory),
or
.B 3
(per-channel diversity with memory).
The value
.B factor
specifies by how much the cost of non-interfering routes is multiplied,
in units of 1/256; the default is 128 (i.e. division by 2).
.TP
.BI \-k " priority"
Specify the priority value used when installing routes into the kernel.
The default is 0.
...
...
@@ -167,6 +185,23 @@ for computing metrics of routes going through this interface depends on
whether link quality estimation is being done. The default is 96 for wired
interfaces, and 256 for wireless ones.
.TP
.BI channel " channel"
Sets the channel for this interface. The value
.I channel
can be either an integer, or one of the strings
.B interfering
or
.BR noninterfering .
The default is to autodetect the channel number for wireless interfaces,
and
.B noninterfering
for wired interfaces.
.TP
.BR faraway " {" true | false }
This specifies whether the network is "far away", in the sense that
networks behind it don't interfere with networks in front of it. By
default, networks are not far away.
.TP
.BI hello\-interval " interval"
This defines the interval between hello packets sent on this interface.
The default is specified with the
...
...
configuration.c
View file @
210b379a
...
...
@@ -429,6 +429,12 @@ parse_nconf(gnc_t gnc, void *closure)
if
(
c
<
-
1
)
goto
error
;
nconf
->
wired
=
v
;
}
else
if
(
strcmp
(
token
,
"faraway"
)
==
0
)
{
int
v
;
c
=
getbool
(
c
,
&
v
,
gnc
,
closure
);
if
(
c
<
-
1
)
goto
error
;
nconf
->
faraway
=
v
;
}
else
if
(
strcmp
(
token
,
"link-quality"
)
==
0
)
{
int
v
;
c
=
getbool
(
c
,
&
v
,
gnc
,
closure
);
...
...
@@ -441,6 +447,28 @@ parse_nconf(gnc_t gnc, void *closure)
if
(
c
<
-
1
)
goto
error
;
nconf
->
split_horizon
=
v
;
}
else
if
(
strcmp
(
token
,
"channel"
)
==
0
)
{
char
*
t
,
*
end
;
c
=
getword
(
c
,
&
t
,
gnc
,
closure
);
if
(
c
<
-
1
)
goto
error
;
if
(
strcmp
(
t
,
"noninterfering"
)
==
0
)
nconf
->
channel
=
NET_CHANNEL_NONINTERFERING
;
else
if
(
strcmp
(
t
,
"interfering"
)
==
0
)
nconf
->
channel
=
NET_CHANNEL_INTERFERING
;
else
{
nconf
->
channel
=
strtol
(
t
,
&
end
,
0
);
if
(
*
end
!=
'\0'
)
goto
error
;
}
free
(
t
);
if
((
nconf
->
channel
<
1
||
nconf
->
channel
>
254
)
&&
nconf
->
channel
!=
NET_CHANNEL_NONINTERFERING
)
goto
error
;
}
else
{
goto
error
;
}
...
...
kernel.h
View file @
210b379a
...
...
@@ -52,6 +52,7 @@ int kernel_interface_ipv4(const char *ifname, int ifindex,
unsigned
char
*
addr_r
);
int
kernel_interface_mtu
(
const
char
*
ifname
,
int
ifindex
);
int
kernel_interface_wireless
(
const
char
*
ifname
,
int
ifindex
);
int
kernel_interface_channel
(
const
char
*
ifname
,
int
ifindex
);
int
kernel_route
(
int
operation
,
const
unsigned
char
*
dest
,
unsigned
short
plen
,
const
unsigned
char
*
gate
,
int
ifindex
,
unsigned
int
metric
,
const
unsigned
char
*
newgate
,
int
newifindex
,
...
...
kernel_netlink.c
View file @
210b379a
...
...
@@ -742,6 +742,81 @@ kernel_interface_wireless(const char *ifname, int ifindex)
return
rc
;
}
/* Sorry for that, but I haven't managed to get <linux/wireless.h>
to include cleanly. */
#define SIOCGIWFREQ 0x8B05
struct
iw_freq
{
int
m
;
short
e
;
unsigned
char
i
;
unsigned
char
flags
;
};
struct
iwreq_subset
{
union
{
char
ifrn_name
[
IFNAMSIZ
];
}
ifr_ifrn
;
union
{
struct
iw_freq
freq
;
}
u
;
};
static
int
freq_to_chan
(
struct
iw_freq
*
freq
)
{
int
m
=
freq
->
m
,
e
=
freq
->
e
;
/* If exponent is 0, assume the channel is encoded directly in m. */
if
(
e
==
0
&&
m
>
0
&&
m
<
254
)
return
m
;
if
(
e
<=
6
)
{
int
mega
,
step
,
c
,
i
;
/* This encodes 1 MHz */
mega
=
1000000
;
for
(
i
=
0
;
i
<
e
;
i
++
)
mega
/=
10
;
/* Channels 1 through 13 are 5 MHz apart, with channel 1 at 2412. */
step
=
5
*
mega
;
c
=
1
+
(
m
-
2412
*
mega
+
step
/
2
)
/
step
;
if
(
c
>=
1
&&
c
<=
13
)
return
c
;
/* Channel 14 is at 2484 MHz */
if
(
c
>=
14
&&
m
<
2484
*
mega
+
step
/
2
)
return
14
;
/* 802.11a channel 36 is at 5180 MHz */
c
=
36
+
(
m
-
5180
*
mega
+
step
/
2
)
/
step
;
if
(
c
>=
34
&&
c
<=
165
)
return
c
;
}
errno
=
ENOENT
;
return
-
1
;
}
int
kernel_interface_channel
(
const
char
*
ifname
,
int
ifindex
)
{
struct
iwreq_subset
iwreq
;
int
rc
;
memset
(
&
iwreq
,
0
,
sizeof
(
iwreq
));
strncpy
(
iwreq
.
ifr_ifrn
.
ifrn_name
,
ifname
,
IFNAMSIZ
);
rc
=
ioctl
(
dgram_socket
,
SIOCGIWFREQ
,
&
iwreq
);
if
(
rc
>=
0
)
return
freq_to_chan
(
&
iwreq
.
u
.
freq
);
else
return
-
1
;
}
int
kernel_route
(
int
operation
,
const
unsigned
char
*
dest
,
unsigned
short
plen
,
const
unsigned
char
*
gate
,
int
ifindex
,
unsigned
int
metric
,
...
...
kernel_socket.c
View file @
210b379a
...
...
@@ -297,6 +297,13 @@ kernel_interface_wireless(const char *ifname, int ifindex)
return
0
;
}
int
kernel_interface_channel
(
const
char
*
ifname
,
int
ifindex
)
{
errno
=
ENOSYS
;
return
-
1
;
}
int
kernel_route
(
int
operation
,
const
unsigned
char
*
dest
,
unsigned
short
plen
,
const
unsigned
char
*
gate
,
int
ifindex
,
unsigned
int
metric
,
...
...
message.c
View file @
210b379a
...
...
@@ -20,6 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
...
...
@@ -58,6 +59,8 @@ struct timeval unicast_flush_timeout = {0, 0};
static
const
unsigned
char
v4prefix
[
16
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0xFF
,
0xFF
,
0
,
0
,
0
,
0
};
/* Parse a network prefix, encoded in the somewhat baroque compressed
representation used by Babel. Return the number of bytes parsed. */
static
int
network_prefix
(
int
ae
,
int
plen
,
unsigned
int
omitted
,
const
unsigned
char
*
p
,
const
unsigned
char
*
dp
,
...
...
@@ -65,6 +68,7 @@ network_prefix(int ae, int plen, unsigned int omitted,
{
unsigned
pb
;
unsigned
char
prefix
[
16
];
int
ret
=
-
1
;
if
(
plen
>=
0
)
pb
=
(
plen
+
7
)
/
8
;
...
...
@@ -79,7 +83,9 @@ network_prefix(int ae, int plen, unsigned int omitted,
memset
(
prefix
,
0
,
16
);
switch
(
ae
)
{
case
0
:
break
;
case
0
:
ret
=
0
;
break
;
case
1
:
if
(
omitted
>
4
||
pb
>
4
||
(
pb
>
omitted
&&
len
<
pb
-
omitted
))
return
-
1
;
...
...
@@ -89,6 +95,7 @@ network_prefix(int ae, int plen, unsigned int omitted,
memcpy
(
prefix
,
dp
,
12
+
omitted
);
}
if
(
pb
>
omitted
)
memcpy
(
prefix
+
12
+
omitted
,
p
,
pb
-
omitted
);
ret
=
pb
-
omitted
;
break
;
case
2
:
if
(
omitted
>
16
||
(
pb
>
omitted
&&
len
<
pb
-
omitted
))
return
-
1
;
...
...
@@ -97,19 +104,68 @@ network_prefix(int ae, int plen, unsigned int omitted,
memcpy
(
prefix
,
dp
,
omitted
);
}
if
(
pb
>
omitted
)
memcpy
(
prefix
+
omitted
,
p
,
pb
-
omitted
);
ret
=
pb
-
omitted
;
break
;
case
3
:
if
(
pb
>
8
&&
len
<
pb
-
8
)
return
-
1
;
prefix
[
0
]
=
0xfe
;
prefix
[
1
]
=
0x80
;
if
(
pb
>
8
)
memcpy
(
prefix
+
8
,
p
,
pb
-
8
);
ret
=
pb
-
8
;
break
;
default:
return
-
1
;
}
mask_prefix
(
p_r
,
prefix
,
plen
<
0
?
128
:
ae
==
1
?
plen
+
96
:
plen
);
return
1
;
return
ret
;
}
static
void
parse_route_attributes
(
const
unsigned
char
*
a
,
int
alen
,
unsigned
char
*
channels
)
{
int
type
,
len
,
i
=
0
;
while
(
i
<
alen
)
{
type
=
a
[
i
];
if
(
type
==
0
)
{
i
++
;
continue
;
}
if
(
i
+
1
>
alen
)
{
fprintf
(
stderr
,
"Received truncated attributes.
\n
"
);
return
;
}
len
=
a
[
i
+
1
];
if
(
i
+
len
>
alen
)
{
fprintf
(
stderr
,
"Received truncated attributes.
\n
"
);
return
;
}
if
(
type
==
1
)
{
/* Nothing. */
}
else
if
(
type
==
2
)
{
if
(
len
>
DIVERSITY_HOPS
)
{
fprintf
(
stderr
,
"Received overlong channel information (%d > %d).
\n
"
,
len
,
DIVERSITY_HOPS
);
len
=
DIVERSITY_HOPS
;
}
if
(
memchr
(
a
+
i
+
2
,
0
,
len
)
!=
NULL
)
{
/* 0 is reserved. */
fprintf
(
stderr
,
"Channel information contains 0!"
);
return
;
}
memset
(
channels
,
0
,
DIVERSITY_HOPS
);
memcpy
(
channels
,
a
+
i
+
2
,
len
);
}
else
{
fprintf
(
stderr
,
"Received unknown route attribute %d.
\n
"
,
type
);
}
i
+=
len
+
2
;
}
}
static
int
...
...
@@ -119,6 +175,12 @@ network_address(int ae, const unsigned char *a, unsigned int len,
return
network_prefix
(
ae
,
-
1
,
0
,
a
,
NULL
,
len
,
a_r
);
}
static
int
channels_len
(
unsigned
char
*
channels
)
{
return
strnlen
((
char
*
)
channels
,
DIVERSITY_HOPS
);
}
void
parse_packet
(
const
unsigned
char
*
from
,
struct
network
*
net
,
const
unsigned
char
*
packet
,
int
packetlen
)
...
...
@@ -275,8 +337,9 @@ parse_packet(const unsigned char *from, struct network *net,
}
else
if
(
type
==
MESSAGE_UPDATE
)
{
unsigned
char
prefix
[
16
],
*
nh
;
unsigned
char
plen
;
unsigned
char
channels
[
DIVERSITY_HOPS
];
unsigned
short
interval
,
seqno
,
metric
;
int
rc
;
int
rc
,
parsed_len
;
if
(
len
<
10
)
{
if
(
len
<
2
||
message
[
3
]
&
0x80
)
have_v4_prefix
=
have_v6_prefix
=
0
;
...
...
@@ -298,6 +361,7 @@ parse_packet(const unsigned char *from, struct network *net,
have_v4_prefix
=
have_v6_prefix
=
0
;
goto
fail
;
}
parsed_len
=
10
+
rc
;
plen
=
message
[
4
]
+
(
message
[
2
]
==
1
?
96
:
0
);
...
...
@@ -352,8 +416,27 @@ parse_packet(const unsigned char *from, struct network *net,
goto
done
;
}
if
((
net
->
flags
&
NET_FARAWAY
))
{
channels
[
0
]
=
0
;
}
else
{
/* This will be overwritten by parse_route_attributes below. */
if
(
metric
<
256
)
{
/* Assume non-interfering (wired) link. */
channels
[
0
]
=
0
;
}
else
{
/* Assume interfering. */
channels
[
0
]
=
NET_CHANNEL_INTERFERING
;
channels
[
1
]
=
0
;
}
if
(
parsed_len
<
len
)
parse_route_attributes
(
message
+
2
+
parsed_len
,
len
-
parsed_len
,
channels
);
}
update_route
(
router_id
,
prefix
,
plen
,
seqno
,
metric
,
interval
,
neigh
,
nh
);
neigh
,
nh
,
channels
,
channels_len
(
channels
));
}
else
if
(
type
==
MESSAGE_REQUEST
)
{
unsigned
char
prefix
[
16
],
plen
;
int
rc
;
...
...
@@ -708,11 +791,18 @@ static void
really_send_update
(
struct
network
*
net
,
const
unsigned
char
*
id
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
unsigned
short
seqno
,
unsigned
short
metric
)
unsigned
short
seqno
,
unsigned
short
metric
,
unsigned
char
*
channels
,
int
channels_len
)
{
int
add_metric
,
v4
,
real_plen
,
omit
=
0
;
const
unsigned
char
*
real_prefix
;
unsigned
short
flags
=
0
;
int
channels_size
;
if
(
diversity_kind
!=
DIVERSITY_CHANNEL
)
channels_len
=
-
1
;
channels_size
=
channels_len
>=
0
?
channels_len
+
2
:
0
;
if
(
!
net_up
(
net
))
return
;
...
...
@@ -768,7 +858,8 @@ really_send_update(struct network *net,
net
->
have_buffered_id
=
1
;
}
start_message
(
net
,
MESSAGE_UPDATE
,
10
+
(
real_plen
+
7
)
/
8
-
omit
);
start_message
(
net
,
MESSAGE_UPDATE
,
10
+
(
real_plen
+
7
)
/
8
-
omit
+
channels_size
);
accumulate_byte
(
net
,
v4
?
1
:
2
);
accumulate_byte
(
net
,
flags
);
accumulate_byte
(
net
,
real_plen
);
...
...
@@ -777,7 +868,14 @@ really_send_update(struct network *net,
accumulate_short
(
net
,
seqno
);
accumulate_short
(
net
,
metric
);
accumulate_bytes
(
net
,
real_prefix
+
omit
,
(
real_plen
+
7
)
/
8
-
omit
);
end_message
(
net
,
MESSAGE_UPDATE
,
10
+
(
real_plen
+
7
)
/
8
-
omit
);
/* Note that an empty channels TLV is different from no such TLV. */
if
(
channels_len
>=
0
)
{
accumulate_byte
(
net
,
2
);
accumulate_byte
(
net
,
channels_len
);
accumulate_bytes
(
net
,
channels
,
channels_len
);
}
end_message
(
net
,
MESSAGE_UPDATE
,
10
+
(
real_plen
+
7
)
/
8
-
omit
+
channels_size
);
if
(
flags
&
0x80
)
{
memcpy
(
net
->
buffered_prefix
,
prefix
,
16
);
...
...
@@ -863,9 +961,6 @@ flushupdates(struct network *net)
qsort
(
b
,
n
,
sizeof
(
struct
buffered_update
),
compare_buffered_updates
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
unsigned
short
seqno
;
unsigned
short
metric
;
/* The same update may be scheduled multiple times before it is
sent out. Since our buffer is now sorted, it is enough to
compare with the previous update. */
...
...
@@ -882,22 +977,50 @@ flushupdates(struct network *net)
if
(
xroute
&&
(
!
route
||
xroute
->
metric
<=
kernel_metric
))
{
really_send_update
(
net
,
myid
,
xroute
->
prefix
,
xroute
->
plen
,
myseqno
,
xroute
->
metric
);
myseqno
,
xroute
->
metric
,
NULL
,
0
);
last_prefix
=
xroute
->
prefix
;
last_plen
=
xroute
->
plen
;
}
else
if
(
route
)
{
unsigned
char
channels
[
DIVERSITY_HOPS
];
int
chlen
;
struct
network
*
route_net
=
route
->
neigh
->
network
;
unsigned
short
metric
;
unsigned
short
seqno
;
seqno
=
route
->
seqno
;
metric
=
route_metric
(
route
);
metric
=
route_interferes
(
route
,
net
)
?
route_metric
(
route
)
:
route_metric_noninterfering
(
route
);
if
(
metric
<
INFINITY
)
satisfy_request
(
route
->
src
->
prefix
,
route
->
src
->
plen
,
seqno
,
route
->
src
->
id
,
net
);
if
((
net
->
flags
&
NET_SPLIT_HORIZON
)
&&
route
->
neigh
->
network
==
net
)
continue
;
if
(
route_net
->
channel
==
NET_CHANNEL_NONINTERFERING
)
{
memcpy
(
channels
,
route
->
channels
,
DIVERSITY_HOPS
);
}
else
{
if
(
route_net
->
channel
==
NET_CHANNEL_UNKNOWN
)
channels
[
0
]
=
NET_CHANNEL_INTERFERING
;
else
{
assert
(
route_net
->
channel
>
0
&&
route_net
->
channel
<=
254
);
channels
[
0
]
=
route_net
->
channel
;
}
memcpy
(
channels
+
1
,
route
->
channels
,
DIVERSITY_HOPS
-
1
);
}
chlen
=
channels_len
(
channels
);
really_send_update
(
net
,
route
->
src
->
id
,
route
->
src
->
prefix
,
route
->
src
->
plen
,
seqno
,
metric
);
seqno
,
metric
,
channels
,
chlen
);
update_source
(
route
->
src
,
seqno
,
metric
);
last_prefix
=
route
->
src
->
prefix
;
last_plen
=
route
->
src
->
plen
;
...
...
@@ -905,7 +1028,7 @@ flushupdates(struct network *net)
/* There's no route for this prefix. This can happen shortly
after an xroute has been retracted, so send a retraction. */
really_send_update
(
net
,
myid
,
b
[
i
].
prefix
,
b
[
i
].
plen
,
myseqno
,
INFINITY
);
myseqno
,
INFINITY
,
NULL
,
-
1
);
}
}
schedule_flush_now
(
net
);
...
...
network.c
View file @
210b379a
...
...
@@ -23,6 +23,7 @@ THE SOFTWARE.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/ioctl.h>
...
...
@@ -183,6 +184,32 @@ check_network_ipv4(struct network *net)
return
0
;
}
int
check_network_channel
(
struct
network
*
net
)
{
int
channel
=
NET_CONF
(
net
,
channel
);
if
(
channel
==
NET_CHANNEL_UNKNOWN
)
{
if
((
net
->
flags
&
NET_WIRED
))
{
channel
=
NET_CHANNEL_NONINTERFERING
;
}
else
{
channel
=
kernel_interface_channel
(
net
->
ifname
,
net
->
ifindex
);
if
(
channel
<
0
)
fprintf
(
stderr
,
"Couldn't determine channel of interface %s: %s.
\n
"
,
net
->
ifname
,
strerror
(
errno
));
if
(
channel
<=
0
)
channel
=
NET_CHANNEL_INTERFERING
;
}
}
if
(
net
->
channel
!=
channel
)
{
net
->
channel
=
channel
;
return
1
;
}
return
0
;
}
int
network_up
(
struct
network
*
net
,
int
up
)
{
...
...
@@ -292,6 +319,9 @@ network_up(struct network *net, int up)
net
->
flags
|=
NET_LQ
;
}
if
(
NET_CONF
(
net
,
faraway
)
==
CONFIG_YES
)
net
->
flags
|=
NET_FARAWAY
;
net
->
activity_time
=
now
.
tv_sec
;
update_hello_interval
(
net
);
/* Since the interface was marked as active above, the
...
...
@@ -364,13 +394,15 @@ network_up(struct network *net, int up)
net
->
numll
=
0
;
}
check_network_channel
(
net
);
update_network_metric
(
net
);
rc
=
check_network_ipv4
(
net
);
debugf
(
"Upped network %s (%s, cost=%d%s).
\n
"
,
debugf
(
"Upped network %s (%s, cost=%d
, channel=%d
%s).
\n
"
,
net
->
ifname
,
(
net
->
flags
&
NET_WIRED
)
?
"wired"
:
"wireless"
,
net
->
cost
,
net
->
channel
,
net
->
ipv4
?
", IPv4"
:
""
);
if
(
up
&&
rc
>
0
)
...
...
@@ -419,6 +451,7 @@ check_networks(void)
network_up
(
net
,
rc
>
0
);
}
check_network_channel
(
net
);
rc
=
check_network_ipv4
(
net
);
if
(
rc
>
0
)
{
send_request
(
net
,
NULL
,
0
);
...
...
network.h
View file @
210b379a
...
...
@@ -35,6 +35,8 @@ struct network_conf {
char
wired
;
char
split_horizon
;
char
lq
;
char
faraway
;
int
channel
;
struct
network_conf
*
next
;
};
...
...
@@ -46,6 +48,12 @@ struct network_conf {
#define NET_WIRED (1<<1)
#define NET_SPLIT_HORIZON (1 << 2)
#define NET_LQ (1 << 3)
#define NET_FARAWAY (1 << 4)
/* Only INTERFERING can appear on the wire. */
#define NET_CHANNEL_UNKNOWN 0
#define NET_CHANNEL_INTERFERING 255
#define NET_CHANNEL_NONINTERFERING -2
struct
network
{
struct
network
*
next
;
...
...
@@ -53,6 +61,7 @@ struct network {
unsigned
int
ifindex
;
unsigned
short
flags
;
unsigned
short
cost
;
int
channel
;
struct
timeval
hello_timeout
;
struct
timeval
update_timeout
;
struct
timeval
flush_timeout
;
...
...
route.c
View file @
210b379a
...
...
@@ -44,6 +44,8 @@ struct route *routes = NULL;
int
numroutes
=
0
,
maxroutes
=
0
;
int
kernel_metric
=
0
;
int
allow_duplicates
=
-
1
;
int
diversity_kind
=
DIVERSITY_NONE
;
int
diversity_factor
=
256
;
/* in units of 1/256 */
int
keep_unfeasible
=
0
;
struct
route
*
...
...
@@ -237,12 +239,11 @@ switch_routes(struct route *old, struct route *new)
}
static
void
change_route_metric
(
struct
route
*
route
,
unsigned
newmetric
)
change_route_metric
(
struct
route
*
route
,
unsigned
refmetric
,
unsigned
cost
,
unsigned
add
)
{
int
old
,
new
;
if
(
route_metric
(
route
)
==
newmetric
)
return
;
int
newmetric
=
MIN
(
refmetric
+
cost
+
add
,
INFINITY
);
old
=
metric_to_kernel
(
route_metric
(
route
));
new
=
metric_to_kernel
(
newmetric
);
...
...
@@ -260,15 +261,16 @@ change_route_metric(struct route *route, unsigned newmetric)
}
}
route
->
metric
=
newmetric
;
route
->
refmetric
=
refmetric
;
route
->
cost
=
cost
;
route
->
add_metric
=
add
;
local_notify_route
(
route
,
LOCAL_CHANGE
);
}
static
void
retract_route
(
struct
route
*
route
)
{
route
->
refmetric
=
INFINITY
;
change_route_metric
(
route
,
INFINITY
);
change_route_metric
(
route
,
INFINITY
,
INFINITY
,
0
);
}
int
...
...
@@ -289,6 +291,46 @@ route_expired(struct route *route)
return
route
->
time
<
now
.
tv_sec
-
route
->
hold_time
;
}
static
int
channels_interfere
(
int
ch1
,
int
ch2
)
{
if
(
ch1
==
NET_CHANNEL_NONINTERFERING
||
ch2
==
NET_CHANNEL_NONINTERFERING
)
return
0
;
if
(
ch1
==
NET_CHANNEL_INTERFERING
||
ch2
==
NET_CHANNEL_INTERFERING
)
return
1
;
return
ch1
==
ch2
;
}
int
route_interferes
(
struct
route
*
route
,
struct
network
*
net
)
{
switch
(
diversity_kind
)
{
case
DIVERSITY_NONE
:
return
1
;
case
DIVERSITY_INTERFACE_1
:
return
route
->
neigh
->
network
==
net
;
case
DIVERSITY_CHANNEL_1
:
case
DIVERSITY_CHANNEL
:
if
(
route
->
neigh
->
network
==
net
)
return
1
;
if
(
channels_interfere
(
net
->
channel
,
route
->
neigh
->
network
->
channel
))
return
1
;
if
(
diversity_kind
==
DIVERSITY_CHANNEL
)
{
int
i
;
for
(
i
=
0
;
i
<
DIVERSITY_HOPS
;
i
++
)
{
if
(
route
->
channels
[
i
]
==
0
)
break
;
if
(
channels_interfere
(
net
->
channel
,
route
->
channels
[
i
]))
return
1
;
}
}
return
0
;
default:
fprintf
(
stderr
,
"Unknown kind of diversity.
\n
"
);
return
1
;
}
}
int
update_feasible
(
struct
source
*
src
,
unsigned
short
seqno
,
unsigned
short
refmetric
)
...
...
@@ -350,16 +392,11 @@ update_route_metric(struct route *route)
route
->
src
->
prefix
,
route
->
src
->
plen
,
neigh
->
address
,
neigh
->
network
->
ifindex
);
int
newmetric
=
MIN
(
route
->
refmetric
+
add_metric
+
neighbour_cost
(
route
->
neigh
),
INFINITY
);
if
(
newmetric
!=
oldmetric
)
{
change_route_metric
(
route
,
newmetric
);
change_route_metric
(
route
,
route
->
refmetric
,
neighbour_cost
(
route
->
neigh
),
add_metric
);
if
(
route_metric
(
route
)
!=
oldmetric
)
route_changed
(
route
,
route
->
src
,
oldmetric
);
}
}
}
/* Called whenever a neighbour's cost changes, to update the metric of
...
...
@@ -400,7 +437,8 @@ struct route *
update_route
(
const
unsigned
char
*
a
,
const
unsigned
char
*
p
,
unsigned
char
plen
,
unsigned
short
seqno
,
unsigned
short
refmetric
,
unsigned
short
interval
,
struct
neighbour
*
neigh
,
const
unsigned
char
*
nexthop
)
struct
neighbour
*
neigh
,
const
unsigned
char
*
nexthop
,
const
unsigned
char
*
channels
,
int
channels_len
)
{
struct
route
*
route
;
struct
source
*
src
;
...
...
@@ -429,7 +467,6 @@ update_route(const unsigned char *a, const unsigned char *p, unsigned char plen,
feasible
=
update_feasible
(
src
,
seqno
,
refmetric
);
route
=
find_route
(
p
,
plen
,
neigh
,
nexthop
);
metric
=
MIN
((
int
)
refmetric
+
neighbour_cost
(
neigh
)
+
add_metric
,
INFINITY
);
if
(
route
)
{
struct
source
*
oldsrc
;
unsigned
short
oldmetric
;
...
...
@@ -459,8 +496,8 @@ update_route(const unsigned char *a, const unsigned char *p, unsigned char plen,
if
((
feasible
||
keep_unfeasible
)
&&
refmetric
<
INFINITY
)
route
->
time
=
now
.
tv_sec
;
route
->
seqno
=
seqno
;
route
->
refmetric
=
refmetric
;
change_route_metric
(
route
,
metric
);
change_route_metric
(
route
,
refmetric
,
neighbour_cost
(
neigh
),
add_
metric
);
route
->
hold_time
=
hold_time
;
route_changed
(
route
,
oldsrc
,
oldmetric
);
...
...
@@ -494,13 +531,18 @@ update_route(const unsigned char *a, const unsigned char *p, unsigned char plen,
route
=
&
routes
[
numroutes
];
route
->
src
=
src
;
route
->
refmetric
=
refmetric
;
route
->
cost
=
neighbour_cost
(
neigh
);
route
->
add_metric
=
add_metric
;
route
->
seqno
=
seqno
;
route
->
metric
=
metric
;
route
->
neigh
=
neigh
;
memcpy
(
route
->
nexthop
,
nexthop
,
16
);
route
->
time
=
now
.
tv_sec
;
route
->
hold_time
=
hold_time
;
route
->
installed
=
0
;
memset
(
&
route
->
channels
,
0
,
sizeof
(
route
->
channels
));
if
(
channels_len
>
0
)
memcpy
(
&
route
->
channels
,
channels
,
MIN
(
channels_len
,
DIVERSITY_HOPS
));
numroutes
++
;
local_notify_route
(
route
,
LOCAL_ADD
);
consider_route
(
route
);
...
...
route.h
View file @
210b379a
...
...
@@ -20,28 +20,50 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#define DIVERSITY_NONE 0
#define DIVERSITY_INTERFACE_1 1
#define DIVERSITY_CHANNEL_1 2
#define DIVERSITY_CHANNEL 3
#define DIVERSITY_HOPS 8
struct
route
{
struct
source
*
src
;
unsigned
short
metric
;
unsigned
short
refmetric
;
unsigned
short
cost
;
unsigned
short
add_metric
;
unsigned
short
seqno
;
struct
neighbour
*
neigh
;
unsigned
char
nexthop
[
16
];
time_t
time
;
unsigned
short
hold_time
;
/* in seconds */
short
installed
;
unsigned
char
channels
[
DIVERSITY_HOPS
];
};
extern
struct
route
*
routes
;
extern
int
numroutes
,
maxroutes
;
extern
int
kernel_metric
,
allow_duplicates
;
extern
int
diversity_kind
,
diversity_factor
;
extern
int
keep_unfeasible
;
static
inline
int
route_metric
(
const
struct
route
*
route
)
{
return
route
->
metric
;
int
m
=
(
int
)
route
->
refmetric
+
route
->
cost
+
route
->
add_metric
;
return
MIN
(
m
,
INFINITY
);
}
extern
struct
route
*
routes
;
extern
int
numroutes
,
maxroutes
;
extern
int
kernel_metric
,
allow_duplicates
;
extern
int
keep_unfeasible
;
static
inline
int
route_metric_noninterfering
(
const
struct
route
*
route
)
{
int
m
=
(
int
)
route
->
refmetric
+
(
diversity_factor
*
route
->
cost
+
128
)
/
256
+
route
->
add_metric
;
m
=
MAX
(
m
,
route
->
refmetric
+
1
);
return
MIN
(
m
,
INFINITY
);
}
struct
route
*
find_route
(
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
struct
neighbour
*
neigh
,
const
unsigned
char
*
nexthop
);
...
...
@@ -56,6 +78,7 @@ void switch_route(struct route *old, struct route *new);
int
route_feasible
(
struct
route
*
route
);
int
route_old
(
struct
route
*
route
);
int
route_expired
(
struct
route
*
route
);
int
route_interferes
(
struct
route
*
route
,
struct
network
*
net
);
int
update_feasible
(
struct
source
*
src
,
unsigned
short
seqno
,
unsigned
short
refmetric
);
struct
route
*
find_best_route
(
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
...
...
@@ -69,7 +92,8 @@ struct route *update_route(const unsigned char *a,
const
unsigned
char
*
p
,
unsigned
char
plen
,
unsigned
short
seqno
,
unsigned
short
refmetric
,
unsigned
short
interval
,
struct
neighbour
*
neigh
,
const
unsigned
char
*
nexthop
);
const
unsigned
char
*
nexthop
,
const
unsigned
char
*
channels
,
int
channels_len
);
void
retract_neighbour_routes
(
struct
neighbour
*
neigh
);
void
send_unfeasible_request
(
struct
neighbour
*
neigh
,
int
force
,
unsigned
short
seqno
,
unsigned
short
metric
,
...
...
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