mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 10:11:53 +00:00
Core: Prepare for multicast
This commit is contained in:
parent
925aa14912
commit
76baa8b38a
@ -64,24 +64,6 @@ static inline int u64_cmp(u64 i1, u64 i2)
|
|||||||
#define PACKED __attribute__((packed))
|
#define PACKED __attribute__((packed))
|
||||||
|
|
||||||
|
|
||||||
/* Microsecond time */
|
|
||||||
|
|
||||||
typedef s64 btime;
|
|
||||||
|
|
||||||
#define S_ *1000000
|
|
||||||
#define MS_ *1000
|
|
||||||
#define US_ *1
|
|
||||||
#define TO_S /1000000
|
|
||||||
#define TO_MS /1000
|
|
||||||
#define TO_US /1
|
|
||||||
|
|
||||||
#ifndef PARSER
|
|
||||||
#define S S_
|
|
||||||
#define MS MS_
|
|
||||||
#define US US_
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Rate limiting */
|
/* Rate limiting */
|
||||||
|
|
||||||
struct tbf {
|
struct tbf {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
|
#ifndef BIRD_HASH_H
|
||||||
|
#define BIRD_HASH_H
|
||||||
|
|
||||||
#define HASH(type) struct { type **data; uint count, order; }
|
#define HASH(type) struct { type **data; uint count, order; }
|
||||||
#define HASH_TYPE(v) typeof(** (v).data)
|
#define HASH_TYPE(v) typeof(** (v).data)
|
||||||
@ -212,3 +213,4 @@ mem_hash(void *p, int s)
|
|||||||
return mem_hash_value(&h);
|
return mem_hash_value(&h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
59
lib/net.c
59
lib/net.c
@ -11,6 +11,10 @@ const char * const net_label[] = {
|
|||||||
[NET_VPN6] = "vpn6",
|
[NET_VPN6] = "vpn6",
|
||||||
[NET_ROA4] = "roa4",
|
[NET_ROA4] = "roa4",
|
||||||
[NET_ROA6] = "roa6",
|
[NET_ROA6] = "roa6",
|
||||||
|
[NET_MREQ4] = "mreq4",
|
||||||
|
[NET_MREQ6] = "mreq6",
|
||||||
|
[NET_MGRP4] = "mgrp4",
|
||||||
|
[NET_MGRP6] = "mgrp6",
|
||||||
};
|
};
|
||||||
|
|
||||||
const u16 net_addr_length[] = {
|
const u16 net_addr_length[] = {
|
||||||
@ -19,7 +23,11 @@ const u16 net_addr_length[] = {
|
|||||||
[NET_VPN4] = sizeof(net_addr_vpn4),
|
[NET_VPN4] = sizeof(net_addr_vpn4),
|
||||||
[NET_VPN6] = sizeof(net_addr_vpn6),
|
[NET_VPN6] = sizeof(net_addr_vpn6),
|
||||||
[NET_ROA4] = sizeof(net_addr_roa4),
|
[NET_ROA4] = sizeof(net_addr_roa4),
|
||||||
[NET_ROA6] = sizeof(net_addr_roa6)
|
[NET_ROA6] = sizeof(net_addr_roa6),
|
||||||
|
[NET_MREQ4] = sizeof(net_addr_mreq4),
|
||||||
|
[NET_MREQ6] = sizeof(net_addr_mreq6),
|
||||||
|
[NET_MGRP4] = sizeof(net_addr_mgrp4),
|
||||||
|
[NET_MGRP6] = sizeof(net_addr_mgrp6),
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 net_max_prefix_length[] = {
|
const u8 net_max_prefix_length[] = {
|
||||||
@ -28,7 +36,11 @@ const u8 net_max_prefix_length[] = {
|
|||||||
[NET_VPN4] = IP4_MAX_PREFIX_LENGTH,
|
[NET_VPN4] = IP4_MAX_PREFIX_LENGTH,
|
||||||
[NET_VPN6] = IP6_MAX_PREFIX_LENGTH,
|
[NET_VPN6] = IP6_MAX_PREFIX_LENGTH,
|
||||||
[NET_ROA4] = IP4_MAX_PREFIX_LENGTH,
|
[NET_ROA4] = IP4_MAX_PREFIX_LENGTH,
|
||||||
[NET_ROA6] = IP6_MAX_PREFIX_LENGTH
|
[NET_ROA6] = IP6_MAX_PREFIX_LENGTH,
|
||||||
|
[NET_MREQ4] = IP4_MAX_PREFIX_LENGTH,
|
||||||
|
[NET_MREQ6] = IP6_MAX_PREFIX_LENGTH,
|
||||||
|
[NET_MGRP4] = IP4_MAX_PREFIX_LENGTH,
|
||||||
|
[NET_MGRP6] = IP6_MAX_PREFIX_LENGTH,
|
||||||
};
|
};
|
||||||
|
|
||||||
const u16 net_max_text_length[] = {
|
const u16 net_max_text_length[] = {
|
||||||
@ -38,6 +50,10 @@ const u16 net_max_text_length[] = {
|
|||||||
[NET_VPN6] = 65, /* "4294967296:4294967296 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
|
[NET_VPN6] = 65, /* "4294967296:4294967296 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
|
||||||
[NET_ROA4] = 34, /* "255.255.255.255/32-32 AS4294967295" */
|
[NET_ROA4] = 34, /* "255.255.255.255/32-32 AS4294967295" */
|
||||||
[NET_ROA6] = 60, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128-128 AS4294967295" */
|
[NET_ROA6] = 60, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128-128 AS4294967295" */
|
||||||
|
[NET_MREQ4] = 15, /* "255.255.255.255" */
|
||||||
|
[NET_MREQ6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
|
||||||
|
[NET_MGRP4] = 15, /* "255.255.255.255" */
|
||||||
|
[NET_MGRP6] = 39, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -60,6 +76,12 @@ net_format(const net_addr *N, char *buf, int buflen)
|
|||||||
return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
|
return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
|
||||||
case NET_ROA6:
|
case NET_ROA6:
|
||||||
return bsnprintf(buf, buflen, "%I6/%u-%u AS%u", n->roa6.prefix, n->roa6.pxlen, n->roa6.max_pxlen, n->roa6.asn);
|
return bsnprintf(buf, buflen, "%I6/%u-%u AS%u", n->roa6.prefix, n->roa6.pxlen, n->roa6.max_pxlen, n->roa6.asn);
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MGRP4:
|
||||||
|
return bsnprintf(buf, buflen, "%I4", n->mgrp4.ga);
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP6:
|
||||||
|
return bsnprintf(buf, buflen, "%I6", n->mgrp6.ga);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -73,11 +95,15 @@ net_pxmask(const net_addr *a)
|
|||||||
case NET_IP4:
|
case NET_IP4:
|
||||||
case NET_VPN4:
|
case NET_VPN4:
|
||||||
case NET_ROA4:
|
case NET_ROA4:
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MGRP4:
|
||||||
return ipa_from_ip4(ip4_mkmask(net4_pxlen(a)));
|
return ipa_from_ip4(ip4_mkmask(net4_pxlen(a)));
|
||||||
|
|
||||||
case NET_IP6:
|
case NET_IP6:
|
||||||
case NET_VPN6:
|
case NET_VPN6:
|
||||||
case NET_ROA6:
|
case NET_ROA6:
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP6:
|
||||||
return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));
|
return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -105,6 +131,12 @@ net_compare(const net_addr *a, const net_addr *b)
|
|||||||
return net_compare_roa4((const net_addr_roa4 *) a, (const net_addr_roa4 *) b);
|
return net_compare_roa4((const net_addr_roa4 *) a, (const net_addr_roa4 *) b);
|
||||||
case NET_ROA6:
|
case NET_ROA6:
|
||||||
return net_compare_roa6((const net_addr_roa6 *) a, (const net_addr_roa6 *) b);
|
return net_compare_roa6((const net_addr_roa6 *) a, (const net_addr_roa6 *) b);
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MGRP4:
|
||||||
|
return net_compare_mgrp4((const net_addr_mgrp4 *) a, (const net_addr_mgrp4 *) b);
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP6:
|
||||||
|
return net_compare_mgrp6((const net_addr_mgrp6 *) a, (const net_addr_mgrp6 *) b);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -124,6 +156,13 @@ net_validate(const net_addr *N)
|
|||||||
case NET_ROA6:
|
case NET_ROA6:
|
||||||
return net_validate_ip6((net_addr_ip6 *) N);
|
return net_validate_ip6((net_addr_ip6 *) N);
|
||||||
|
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MGRP4:
|
||||||
|
return ip4_classify(((net_addr_mgrp4 *) N)->ga) & IADDR_MULTICAST;
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP6:
|
||||||
|
return ip6_classify(&((net_addr_mgrp6 *) N)->ga) & IADDR_MULTICAST;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -164,6 +203,13 @@ net_classify(const net_addr *N)
|
|||||||
case NET_VPN6:
|
case NET_VPN6:
|
||||||
case NET_ROA6:
|
case NET_ROA6:
|
||||||
return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
|
return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
|
||||||
|
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MGRP4:
|
||||||
|
return ip4_classify(n->mgrp4.ga);
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP6:
|
||||||
|
return ip6_classify(&n->mgrp6.ga);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IADDR_INVALID;
|
return IADDR_INVALID;
|
||||||
@ -188,6 +234,15 @@ ipa_in_netX(const ip_addr a, const net_addr *n)
|
|||||||
return ip6_zero(ip6_and(ip6_xor(ipa_to_ip6(a), net6_prefix(n)),
|
return ip6_zero(ip6_and(ip6_xor(ipa_to_ip6(a), net6_prefix(n)),
|
||||||
ip6_mkmask(net6_pxlen(n))));
|
ip6_mkmask(net6_pxlen(n))));
|
||||||
|
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MGRP4:
|
||||||
|
if (!ipa_is_ip4(a)) return 0;
|
||||||
|
return ip4_equal(ipa_to_ip4(a), ((net_addr_mgrp4 *) n)->ga);
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP6:
|
||||||
|
if (ipa_is_ip4(a)) return 0;
|
||||||
|
return ip6_equal(ipa_to_ip6(a), ((net_addr_mgrp6 *) n)->ga);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
181
lib/net.h
181
lib/net.h
@ -19,7 +19,11 @@
|
|||||||
#define NET_VPN6 4
|
#define NET_VPN6 4
|
||||||
#define NET_ROA4 5
|
#define NET_ROA4 5
|
||||||
#define NET_ROA6 6
|
#define NET_ROA6 6
|
||||||
#define NET_MAX 7
|
#define NET_MREQ4 7
|
||||||
|
#define NET_MREQ6 8
|
||||||
|
#define NET_MGRP4 9
|
||||||
|
#define NET_MGRP6 10
|
||||||
|
#define NET_MAX 11
|
||||||
|
|
||||||
#define NB_IP4 (1 << NET_IP4)
|
#define NB_IP4 (1 << NET_IP4)
|
||||||
#define NB_IP6 (1 << NET_IP6)
|
#define NB_IP6 (1 << NET_IP6)
|
||||||
@ -27,8 +31,16 @@
|
|||||||
#define NB_VPN6 (1 << NET_VPN6)
|
#define NB_VPN6 (1 << NET_VPN6)
|
||||||
#define NB_ROA4 (1 << NET_ROA4)
|
#define NB_ROA4 (1 << NET_ROA4)
|
||||||
#define NB_ROA6 (1 << NET_ROA6)
|
#define NB_ROA6 (1 << NET_ROA6)
|
||||||
|
#define NB_MREQ4 (1 << NET_MREQ4)
|
||||||
|
#define NB_MREQ6 (1 << NET_MREQ6)
|
||||||
|
#define NB_MGRP4 (1 << NET_MGRP4)
|
||||||
|
#define NB_MGRP6 (1 << NET_MGRP6)
|
||||||
|
|
||||||
#define NB_IP (NB_IP4 | NB_IP6)
|
#define NB_IP (NB_IP4 | NB_IP6)
|
||||||
|
#define NB_MREQ (NB_MREQ4 | NB_MREQ6)
|
||||||
|
#define NB_MGRP (NB_MGRP4 | NB_MGRP6)
|
||||||
|
#define NB_MCAST (NB_MREQ | NB_MGRP)
|
||||||
|
#define NB_6 (NB_IP6 | NB_VPN6 | NB_MREQ6 | NB_MGRP6)
|
||||||
#define NB_ANY 0xffffffff
|
#define NB_ANY 0xffffffff
|
||||||
|
|
||||||
|
|
||||||
@ -88,6 +100,36 @@ typedef struct net_addr_roa6 {
|
|||||||
u32 asn;
|
u32 asn;
|
||||||
} net_addr_roa6;
|
} net_addr_roa6;
|
||||||
|
|
||||||
|
typedef struct net_addr_mreq4 {
|
||||||
|
u8 type;
|
||||||
|
u8 pxlen;
|
||||||
|
u16 length;
|
||||||
|
ip4_addr ga;
|
||||||
|
unsigned ifindex;
|
||||||
|
} net_addr_mreq4;
|
||||||
|
|
||||||
|
typedef struct net_addr_mreq6 {
|
||||||
|
u8 type;
|
||||||
|
u8 pxlen;
|
||||||
|
u16 length;
|
||||||
|
ip6_addr ga;
|
||||||
|
unsigned ifindex;
|
||||||
|
} net_addr_mreq6;
|
||||||
|
|
||||||
|
typedef struct net_addr_mgrp4 {
|
||||||
|
u8 type;
|
||||||
|
u8 pxlen;
|
||||||
|
u16 length;
|
||||||
|
ip4_addr ga;
|
||||||
|
} net_addr_mgrp4;
|
||||||
|
|
||||||
|
typedef struct net_addr_mgrp6 {
|
||||||
|
u8 type;
|
||||||
|
u8 pxlen;
|
||||||
|
u16 length;
|
||||||
|
ip6_addr ga;
|
||||||
|
} net_addr_mgrp6;
|
||||||
|
|
||||||
typedef union net_addr_union {
|
typedef union net_addr_union {
|
||||||
net_addr n;
|
net_addr n;
|
||||||
net_addr_ip4 ip4;
|
net_addr_ip4 ip4;
|
||||||
@ -96,6 +138,10 @@ typedef union net_addr_union {
|
|||||||
net_addr_vpn6 vpn6;
|
net_addr_vpn6 vpn6;
|
||||||
net_addr_roa4 roa4;
|
net_addr_roa4 roa4;
|
||||||
net_addr_roa6 roa6;
|
net_addr_roa6 roa6;
|
||||||
|
net_addr_mreq4 mreq4;
|
||||||
|
net_addr_mreq6 mreq6;
|
||||||
|
net_addr_mgrp4 mgrp4;
|
||||||
|
net_addr_mgrp6 mgrp6;
|
||||||
} net_addr_union;
|
} net_addr_union;
|
||||||
|
|
||||||
|
|
||||||
@ -125,6 +171,17 @@ extern const u16 net_max_text_length[];
|
|||||||
#define NET_ADDR_ROA6(prefix,pxlen,max_pxlen,asn) \
|
#define NET_ADDR_ROA6(prefix,pxlen,max_pxlen,asn) \
|
||||||
((net_addr_roa6) { NET_ROA6, pxlen, sizeof(net_addr_roa6), prefix, max_pxlen, asn })
|
((net_addr_roa6) { NET_ROA6, pxlen, sizeof(net_addr_roa6), prefix, max_pxlen, asn })
|
||||||
|
|
||||||
|
#define NET_ADDR_MREQ4(ga, ifindex) \
|
||||||
|
((net_addr_mreq4) { NET_MREQ4, IP4_MAX_PREFIX_LENGTH, sizeof(net_addr_mreq4), ga, ifindex })
|
||||||
|
|
||||||
|
#define NET_ADDR_MREQ6(ga, ifindex) \
|
||||||
|
((net_addr_mreq6) { NET_MREQ6, IP6_MAX_PREFIX_LENGTH, sizeof(net_addr_mreq6), ga, ifindex })
|
||||||
|
|
||||||
|
#define NET_ADDR_MGRP4(ga) \
|
||||||
|
((net_addr_mgrp4) { NET_MGRP4, IP4_MAX_PREFIX_LENGTH, sizeof(net_addr_mgrp4), ga })
|
||||||
|
|
||||||
|
#define NET_ADDR_MGRP6(ga) \
|
||||||
|
((net_addr_mgrp6) { NET_MGRP6, IP6_MAX_PREFIX_LENGTH, sizeof(net_addr_mgrp6), ga })
|
||||||
|
|
||||||
|
|
||||||
static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen)
|
static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen)
|
||||||
@ -145,6 +202,18 @@ static inline void net_fill_roa4(net_addr *a, ip4_addr prefix, uint pxlen, uint
|
|||||||
static inline void net_fill_roa6(net_addr *a, ip6_addr prefix, uint pxlen, uint max_pxlen, u32 asn)
|
static inline void net_fill_roa6(net_addr *a, ip6_addr prefix, uint pxlen, uint max_pxlen, u32 asn)
|
||||||
{ *(net_addr_roa6 *)a = NET_ADDR_ROA6(prefix, pxlen, max_pxlen, asn); }
|
{ *(net_addr_roa6 *)a = NET_ADDR_ROA6(prefix, pxlen, max_pxlen, asn); }
|
||||||
|
|
||||||
|
static inline void net_fill_mreq4(net_addr *a, ip4_addr ga, unsigned ifindex)
|
||||||
|
{ *(net_addr_mreq4 *)a = NET_ADDR_MREQ4(ga, ifindex); }
|
||||||
|
|
||||||
|
static inline void net_fill_mreq6(net_addr *a, ip6_addr ga, unsigned ifindex)
|
||||||
|
{ *(net_addr_mreq6 *)a = NET_ADDR_MREQ6(ga, ifindex); }
|
||||||
|
|
||||||
|
static inline void net_fill_mgrp4(net_addr *a, ip4_addr ga)
|
||||||
|
{ *(net_addr_mgrp4 *)a = NET_ADDR_MGRP4(ga); }
|
||||||
|
|
||||||
|
static inline void net_fill_mgrp6(net_addr *a, ip6_addr ga)
|
||||||
|
{ *(net_addr_mgrp6 *)a = NET_ADDR_MGRP6(ga); }
|
||||||
|
|
||||||
static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen)
|
static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen)
|
||||||
{
|
{
|
||||||
if (ipa_is_ip4(prefix))
|
if (ipa_is_ip4(prefix))
|
||||||
@ -161,6 +230,21 @@ static inline void net_fill_ip_host(net_addr *a, ip_addr prefix)
|
|||||||
net_fill_ip6(a, ipa_to_ip6(prefix), IP6_MAX_PREFIX_LENGTH);
|
net_fill_ip6(a, ipa_to_ip6(prefix), IP6_MAX_PREFIX_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void net_fill_mreq(net_addr *a, ip_addr ga, unsigned ifindex)
|
||||||
|
{
|
||||||
|
if (ipa_is_ip4(ga))
|
||||||
|
net_fill_mreq4(a, ipa_to_ip4(ga), ifindex);
|
||||||
|
else
|
||||||
|
net_fill_mreq6(a, ipa_to_ip6(ga), ifindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void net_fill_mgrp(net_addr *a, ip_addr ga)
|
||||||
|
{
|
||||||
|
if (ipa_is_ip4(ga))
|
||||||
|
net_fill_mgrp4(a, ipa_to_ip4(ga));
|
||||||
|
else
|
||||||
|
net_fill_mgrp6(a, ipa_to_ip6(ga));
|
||||||
|
}
|
||||||
|
|
||||||
static inline int net_val_match(u8 type, u32 mask)
|
static inline int net_val_match(u8 type, u32 mask)
|
||||||
{ return !!((1 << type) & mask); }
|
{ return !!((1 << type) & mask); }
|
||||||
@ -185,11 +269,15 @@ static inline ip_addr net_prefix(const net_addr *a)
|
|||||||
case NET_IP4:
|
case NET_IP4:
|
||||||
case NET_VPN4:
|
case NET_VPN4:
|
||||||
case NET_ROA4:
|
case NET_ROA4:
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MGRP4:
|
||||||
return ipa_from_ip4(net4_prefix(a));
|
return ipa_from_ip4(net4_prefix(a));
|
||||||
|
|
||||||
case NET_IP6:
|
case NET_IP6:
|
||||||
case NET_VPN6:
|
case NET_VPN6:
|
||||||
case NET_ROA6:
|
case NET_ROA6:
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP6:
|
||||||
return ipa_from_ip6(net6_prefix(a));
|
return ipa_from_ip6(net6_prefix(a));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -208,6 +296,39 @@ static inline uint net_pxlen(const net_addr *a)
|
|||||||
|
|
||||||
ip_addr net_pxmask(const net_addr *a);
|
ip_addr net_pxmask(const net_addr *a);
|
||||||
|
|
||||||
|
static inline int net_is_host(const net_addr *a)
|
||||||
|
{
|
||||||
|
switch (a->type)
|
||||||
|
{
|
||||||
|
case NET_IP4:
|
||||||
|
case NET_VPN4: return net4_pxlen(a) == IP4_MAX_PREFIX_LENGTH;
|
||||||
|
case NET_IP6:
|
||||||
|
case NET_VPN6: return net6_pxlen(a) == IP6_MAX_PREFIX_LENGTH;
|
||||||
|
case NET_MREQ4:
|
||||||
|
case NET_MREQ6:
|
||||||
|
case NET_MGRP4:
|
||||||
|
case NET_MGRP6: return 1;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int net_is_v6(net_addr *a)
|
||||||
|
{
|
||||||
|
return net_type_match(a, NB_6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int net_ifindex(net_addr *a)
|
||||||
|
{
|
||||||
|
switch (a->type)
|
||||||
|
{
|
||||||
|
case NET_MREQ4:
|
||||||
|
return ((net_addr_mreq4 *) a)->ifindex;
|
||||||
|
case NET_MREQ6:
|
||||||
|
return ((net_addr_mreq6 *) a)->ifindex;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static inline int net_equal(const net_addr *a, const net_addr *b)
|
static inline int net_equal(const net_addr *a, const net_addr *b)
|
||||||
{ return (a->length == b->length) && !memcmp(a, b, a->length); }
|
{ return (a->length == b->length) && !memcmp(a, b, a->length); }
|
||||||
@ -236,6 +357,18 @@ static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_r
|
|||||||
static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
|
static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
|
||||||
{ return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
|
{ return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
|
||||||
|
|
||||||
|
static inline int net_equal_mreq4(const net_addr_mreq4 *a, const net_addr_mreq4 *b)
|
||||||
|
{ return !memcmp(a, b, sizeof(net_addr_mreq4)); }
|
||||||
|
|
||||||
|
static inline int net_equal_mreq6(const net_addr_mreq6 *a, const net_addr_mreq6 *b)
|
||||||
|
{ return !memcmp(a, b, sizeof(net_addr_mreq6)); }
|
||||||
|
|
||||||
|
static inline int net_equal_mgrp4(const net_addr_mgrp4 *a, const net_addr_mgrp4 *b)
|
||||||
|
{ return !memcmp(a, b, sizeof(net_addr_mgrp4)); }
|
||||||
|
|
||||||
|
static inline int net_equal_mgrp6(const net_addr_mgrp6 *a, const net_addr_mgrp6 *b)
|
||||||
|
{ return !memcmp(a, b, sizeof(net_addr_mgrp6)); }
|
||||||
|
|
||||||
|
|
||||||
static inline int net_zero_ip4(const net_addr_ip4 *a)
|
static inline int net_zero_ip4(const net_addr_ip4 *a)
|
||||||
{ return !a->pxlen && ip4_zero(a->prefix); }
|
{ return !a->pxlen && ip4_zero(a->prefix); }
|
||||||
@ -255,6 +388,18 @@ static inline int net_zero_roa4(const net_addr_roa4 *a)
|
|||||||
static inline int net_zero_roa6(const net_addr_roa6 *a)
|
static inline int net_zero_roa6(const net_addr_roa6 *a)
|
||||||
{ return !a->pxlen && ip6_zero(a->prefix) && !a->max_pxlen && !a->asn; }
|
{ return !a->pxlen && ip6_zero(a->prefix) && !a->max_pxlen && !a->asn; }
|
||||||
|
|
||||||
|
static inline int net_zero_mreq4(const net_addr_mreq4 *a)
|
||||||
|
{ return ip4_zero(a->ga) && !a->ifindex; }
|
||||||
|
|
||||||
|
static inline int net_zero_mreq6(const net_addr_mreq6 *a)
|
||||||
|
{ return ip6_zero(a->ga) && !a->ifindex; }
|
||||||
|
|
||||||
|
static inline int net_zero_mgrp4(const net_addr_mgrp4 *a)
|
||||||
|
{ return ip4_zero(a->ga); }
|
||||||
|
|
||||||
|
static inline int net_zero_mgrp6(const net_addr_mgrp6 *a)
|
||||||
|
{ return ip6_zero(a->ga); }
|
||||||
|
|
||||||
|
|
||||||
static inline int net_compare_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b)
|
static inline int net_compare_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b)
|
||||||
{ return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
{ return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
||||||
@ -274,6 +419,18 @@ static inline int net_compare_roa4(const net_addr_roa4 *a, const net_addr_roa4 *
|
|||||||
static inline int net_compare_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
|
static inline int net_compare_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
|
||||||
{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->max_pxlen, b->max_pxlen) ?: uint_cmp(a->asn, b->asn); }
|
{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->max_pxlen, b->max_pxlen) ?: uint_cmp(a->asn, b->asn); }
|
||||||
|
|
||||||
|
static inline int net_compare_mreq4(const net_addr_mreq4 *a, const net_addr_mreq4 *b)
|
||||||
|
{ return ip4_compare(a->ga, b->ga) ?: uint_cmp(a->ifindex, b->ifindex); }
|
||||||
|
|
||||||
|
static inline int net_compare_mreq6(const net_addr_mreq6 *a, const net_addr_mreq6 *b)
|
||||||
|
{ return ip6_compare(a->ga, b->ga) ?: uint_cmp(a->ifindex, b->ifindex); }
|
||||||
|
|
||||||
|
static inline int net_compare_mgrp4(const net_addr_mgrp4 *a, const net_addr_mgrp4 *b)
|
||||||
|
{ return ip4_compare(a->ga, b->ga); }
|
||||||
|
|
||||||
|
static inline int net_compare_mgrp6(const net_addr_mgrp6 *a, const net_addr_mgrp6 *b)
|
||||||
|
{ return ip6_compare(a->ga, b->ga); }
|
||||||
|
|
||||||
int net_compare(const net_addr *a, const net_addr *b);
|
int net_compare(const net_addr *a, const net_addr *b);
|
||||||
|
|
||||||
|
|
||||||
@ -298,6 +455,17 @@ static inline void net_copy_roa4(net_addr_roa4 *dst, const net_addr_roa4 *src)
|
|||||||
static inline void net_copy_roa6(net_addr_roa6 *dst, const net_addr_roa6 *src)
|
static inline void net_copy_roa6(net_addr_roa6 *dst, const net_addr_roa6 *src)
|
||||||
{ memcpy(dst, src, sizeof(net_addr_roa6)); }
|
{ memcpy(dst, src, sizeof(net_addr_roa6)); }
|
||||||
|
|
||||||
|
static inline void net_copy_mreq4(net_addr_mreq4 *dst, const net_addr_mreq4 *src)
|
||||||
|
{ memcpy(dst, src, sizeof(net_addr_mreq4)); }
|
||||||
|
|
||||||
|
static inline void net_copy_mreq6(net_addr_mreq6 *dst, const net_addr_mreq6 *src)
|
||||||
|
{ memcpy(dst, src, sizeof(net_addr_mreq6)); }
|
||||||
|
|
||||||
|
static inline void net_copy_mgrp4(net_addr_mgrp4 *dst, const net_addr_mgrp4 *src)
|
||||||
|
{ memcpy(dst, src, sizeof(net_addr_mgrp4)); }
|
||||||
|
|
||||||
|
static inline void net_copy_mgrp6(net_addr_mgrp6 *dst, const net_addr_mgrp6 *src)
|
||||||
|
{ memcpy(dst, src, sizeof(net_addr_mgrp6)); }
|
||||||
|
|
||||||
static inline u32 net_hash_ip4(const net_addr_ip4 *n)
|
static inline u32 net_hash_ip4(const net_addr_ip4 *n)
|
||||||
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
||||||
@ -321,6 +489,17 @@ static inline u32 net_hash_roa4(const net_addr_roa4 *n)
|
|||||||
static inline u32 net_hash_roa6(const net_addr_roa6 *n)
|
static inline u32 net_hash_roa6(const net_addr_roa6 *n)
|
||||||
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
||||||
|
|
||||||
|
static inline u32 net_hash_mreq4(const net_addr_mreq4 *n)
|
||||||
|
{ return ip4_hash(n->ga) ^ u64_hash(n->ifindex); }
|
||||||
|
|
||||||
|
static inline u32 net_hash_mreq6(const net_addr_mreq6 *n)
|
||||||
|
{ return ip6_hash(n->ga) ^ u64_hash(n->ifindex); }
|
||||||
|
|
||||||
|
static inline u32 net_hash_mgrp4(const net_addr_mgrp4 *n)
|
||||||
|
{ return ip4_hash(n->ga); }
|
||||||
|
|
||||||
|
static inline u32 net_hash_mgrp6(const net_addr_mgrp6 *n)
|
||||||
|
{ return ip6_hash(n->ga); }
|
||||||
|
|
||||||
static inline int net_validate_ip4(const net_addr_ip4 *n)
|
static inline int net_validate_ip4(const net_addr_ip4 *n)
|
||||||
{
|
{
|
||||||
|
@ -364,6 +364,9 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
|
|||||||
case 'o':
|
case 'o':
|
||||||
base = 8;
|
base = 8;
|
||||||
break;
|
break;
|
||||||
|
case 'b':
|
||||||
|
base = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'X':
|
case 'X':
|
||||||
flags |= LARGE;
|
flags |= LARGE;
|
||||||
|
@ -77,6 +77,7 @@ static inline int sk_send_buffer_empty(sock *sk)
|
|||||||
int sk_setup_multicast(sock *s); /* Prepare UDP or IP socket for multicasting */
|
int sk_setup_multicast(sock *s); /* Prepare UDP or IP socket for multicasting */
|
||||||
int sk_join_group(sock *s, ip_addr maddr); /* Join multicast group on sk iface */
|
int sk_join_group(sock *s, ip_addr maddr); /* Join multicast group on sk iface */
|
||||||
int sk_leave_group(sock *s, ip_addr maddr); /* Leave multicast group on sk iface */
|
int sk_leave_group(sock *s, ip_addr maddr); /* Leave multicast group on sk iface */
|
||||||
|
int sk_set_router_alert(sock *s, int ra);
|
||||||
int sk_setup_broadcast(sock *s);
|
int sk_setup_broadcast(sock *s);
|
||||||
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
|
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
|
||||||
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
|
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
|
||||||
|
@ -65,7 +65,7 @@ CF_DECLS
|
|||||||
|
|
||||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
||||||
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
|
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
|
||||||
CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6)
|
CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6, MREQ4, MREQ6, MGRP4, MGRP6)
|
||||||
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
|
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
|
||||||
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
||||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE) /* ,ROA */
|
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE) /* ,ROA */
|
||||||
@ -148,6 +148,10 @@ net_type:
|
|||||||
| VPN6 { $$ = NET_VPN6; }
|
| VPN6 { $$ = NET_VPN6; }
|
||||||
| ROA4 { $$ = NET_ROA4; }
|
| ROA4 { $$ = NET_ROA4; }
|
||||||
| ROA6 { $$ = NET_ROA6; }
|
| ROA6 { $$ = NET_ROA6; }
|
||||||
|
| MREQ4 { $$ = NET_MREQ4; }
|
||||||
|
| MREQ6 { $$ = NET_MREQ6; }
|
||||||
|
| MGRP4 { $$ = NET_MGRP4; }
|
||||||
|
| MGRP6 { $$ = NET_MGRP6; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
11
nest/iface.c
11
nest/iface.c
@ -502,6 +502,17 @@ ifa_same(struct ifa *a, struct ifa *b)
|
|||||||
return ipa_equal(a->ip, b->ip) && net_equal(&a->prefix, &b->prefix);
|
return ipa_equal(a->ip, b->ip) && net_equal(&a->prefix, &b->prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ifa *
|
||||||
|
ifa_find_match(struct iface *i, u32 mask)
|
||||||
|
{
|
||||||
|
struct ifa *a;
|
||||||
|
|
||||||
|
WALK_LIST(a, i->addrs)
|
||||||
|
if (net_type_match(&a->prefix, mask))
|
||||||
|
return a;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ifa_update - update interface address
|
* ifa_update - update interface address
|
||||||
|
@ -88,6 +88,7 @@ void if_show(void);
|
|||||||
void if_show_summary(void);
|
void if_show_summary(void);
|
||||||
struct iface *if_update(struct iface *);
|
struct iface *if_update(struct iface *);
|
||||||
void if_delete(struct iface *old);
|
void if_delete(struct iface *old);
|
||||||
|
struct ifa *ifa_find_match(struct iface *i, u32 mask);
|
||||||
struct ifa *ifa_update(struct ifa *);
|
struct ifa *ifa_update(struct ifa *);
|
||||||
void ifa_delete(struct ifa *);
|
void ifa_delete(struct ifa *);
|
||||||
void if_start_update(void);
|
void if_start_update(void);
|
||||||
|
19
nest/route.h
19
nest/route.h
@ -200,6 +200,8 @@ struct hostentry {
|
|||||||
u32 igp_metric; /* Chosen route IGP metric */
|
u32 igp_metric; /* Chosen route IGP metric */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define RTE_MGRP_MAXVIFS 32
|
||||||
|
|
||||||
typedef struct rte {
|
typedef struct rte {
|
||||||
struct rte *next;
|
struct rte *next;
|
||||||
net *net; /* Network this RTE belongs to */
|
net *net; /* Network this RTE belongs to */
|
||||||
@ -235,6 +237,9 @@ typedef struct rte {
|
|||||||
u64 router_id; /* Babel router id */
|
u64 router_id; /* Babel router id */
|
||||||
} babel;
|
} babel;
|
||||||
#endif
|
#endif
|
||||||
|
struct {
|
||||||
|
u32 oifs, iifs; /* Bitmaps for iifs and oifs. Use RTE_MGRP_* macros to manipulate. */
|
||||||
|
} mkrt;
|
||||||
struct { /* Routes generated by krt sync (both temporary and inherited ones) */
|
struct { /* Routes generated by krt sync (both temporary and inherited ones) */
|
||||||
s8 src; /* Alleged route source (see krt.h) */
|
s8 src; /* Alleged route source (see krt.h) */
|
||||||
u8 proto; /* Kernel source protocol ID */
|
u8 proto; /* Kernel source protocol ID */
|
||||||
@ -269,6 +274,13 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED);
|
|||||||
#define RIC_REJECT -1 /* Rejected by protocol */
|
#define RIC_REJECT -1 /* Rejected by protocol */
|
||||||
#define RIC_DROP -2 /* Silently dropped by protocol */
|
#define RIC_DROP -2 /* Silently dropped by protocol */
|
||||||
|
|
||||||
|
#define RTE_MGRP_SET(iface,m) ((m)|=(1<<if_get_vifi((iface))))
|
||||||
|
#define RTE_MGRP_CLR(iface,m) ((m)&=~(1<<if_get_vifi((iface))))
|
||||||
|
#define RTE_MGRP_ISSET(iface,m) ((m)&(1<<if_get_vifi((iface))))
|
||||||
|
#define RTE_MGRP_CLRALL(m) ((m)=0)
|
||||||
|
#define RTE_MGRP_COPY(mfrom,mto) ((mto)=(mfrom))
|
||||||
|
#define RTE_MGRP_SAME(m1,m2) ((m1)==(m2))
|
||||||
|
|
||||||
struct config;
|
struct config;
|
||||||
|
|
||||||
void rt_init(void);
|
void rt_init(void);
|
||||||
@ -287,10 +299,13 @@ void rte_update2(struct channel *c, net_addr *n, rte *new, struct rte_src *src);
|
|||||||
/* rte_update() moved to protocol.h to avoid dependency conflicts */
|
/* rte_update() moved to protocol.h to avoid dependency conflicts */
|
||||||
void rte_discard(rtable *tab, rte *old);
|
void rte_discard(rtable *tab, rte *old);
|
||||||
int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
|
int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
|
||||||
|
int rt_examine2(net *n, struct proto *p, struct filter *filter, void (*callback)(struct proto *, void *, rte *), void *data);
|
||||||
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, int silent);
|
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, int silent);
|
||||||
void rt_refresh_begin(rtable *t, struct channel *c);
|
void rt_refresh_begin(rtable *t, struct channel *c);
|
||||||
void rt_refresh_end(rtable *t, struct channel *c);
|
void rt_refresh_end(rtable *t, struct channel *c);
|
||||||
|
int rt_route(struct channel *c, net_addr *net, void (*callback)(struct proto *, void *, rte *), void *data);
|
||||||
void rt_schedule_prune(rtable *t);
|
void rt_schedule_prune(rtable *t);
|
||||||
|
u32 rt_get_igp_metric(rte *rt);
|
||||||
void rte_dump(rte *);
|
void rte_dump(rte *);
|
||||||
void rte_free(rte *);
|
void rte_free(rte *);
|
||||||
rte *rte_do_cow(rte *);
|
rte *rte_do_cow(rte *);
|
||||||
@ -396,7 +411,9 @@ typedef struct rta {
|
|||||||
#define RTD_UNREACHABLE 3 /* Reject as unreachable */
|
#define RTD_UNREACHABLE 3 /* Reject as unreachable */
|
||||||
#define RTD_PROHIBIT 4 /* Administratively prohibited */
|
#define RTD_PROHIBIT 4 /* Administratively prohibited */
|
||||||
#define RTD_MULTIPATH 5 /* Multipath route (nexthops != NULL) */
|
#define RTD_MULTIPATH 5 /* Multipath route (nexthops != NULL) */
|
||||||
#define RTD_NONE 6 /* Invalid RTD */
|
#define RTD_MREQUEST 6 /* Multicast pseudoroute */
|
||||||
|
#define RTD_MULTICAST 7 /* Multicast pseudoroute */
|
||||||
|
#define RTD_NONE 8 /* Invalid RTD */
|
||||||
|
|
||||||
/* Flags for net->n.flags, used by kernel syncer */
|
/* Flags for net->n.flags, used by kernel syncer */
|
||||||
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
|
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
|
||||||
|
@ -193,6 +193,10 @@ fib_hash(struct fib *f, const net_addr *a)
|
|||||||
case NET_VPN6: return FIB_HASH(f, a, vpn6);
|
case NET_VPN6: return FIB_HASH(f, a, vpn6);
|
||||||
case NET_ROA4: return FIB_HASH(f, a, roa4);
|
case NET_ROA4: return FIB_HASH(f, a, roa4);
|
||||||
case NET_ROA6: return FIB_HASH(f, a, roa6);
|
case NET_ROA6: return FIB_HASH(f, a, roa6);
|
||||||
|
case NET_MREQ4: return FIB_HASH(f, a, mreq4);
|
||||||
|
case NET_MREQ6: return FIB_HASH(f, a, mreq6);
|
||||||
|
case NET_MGRP4: return FIB_HASH(f, a, mgrp4);
|
||||||
|
case NET_MGRP6: return FIB_HASH(f, a, mgrp6);
|
||||||
default: bug("invalid type");
|
default: bug("invalid type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,6 +231,10 @@ fib_find(struct fib *f, const net_addr *a)
|
|||||||
case NET_VPN6: return FIB_FIND(f, a, vpn6);
|
case NET_VPN6: return FIB_FIND(f, a, vpn6);
|
||||||
case NET_ROA4: return FIB_FIND(f, a, roa4);
|
case NET_ROA4: return FIB_FIND(f, a, roa4);
|
||||||
case NET_ROA6: return FIB_FIND(f, a, roa6);
|
case NET_ROA6: return FIB_FIND(f, a, roa6);
|
||||||
|
case NET_MREQ4: return FIB_FIND(f, a, mreq4);
|
||||||
|
case NET_MREQ6: return FIB_FIND(f, a, mreq6);
|
||||||
|
case NET_MGRP4: return FIB_FIND(f, a, mgrp4);
|
||||||
|
case NET_MGRP6: return FIB_FIND(f, a, mgrp6);
|
||||||
default: bug("invalid type");
|
default: bug("invalid type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,6 +252,10 @@ fib_insert(struct fib *f, const net_addr *a, struct fib_node *e)
|
|||||||
case NET_VPN6: FIB_INSERT(f, a, e, vpn6); return;
|
case NET_VPN6: FIB_INSERT(f, a, e, vpn6); return;
|
||||||
case NET_ROA4: FIB_INSERT(f, a, e, roa4); return;
|
case NET_ROA4: FIB_INSERT(f, a, e, roa4); return;
|
||||||
case NET_ROA6: FIB_INSERT(f, a, e, roa6); return;
|
case NET_ROA6: FIB_INSERT(f, a, e, roa6); return;
|
||||||
|
case NET_MREQ4: FIB_INSERT(f, a, e, mreq4); return;
|
||||||
|
case NET_MREQ6: FIB_INSERT(f, a, e, mreq6); return;
|
||||||
|
case NET_MGRP4: FIB_INSERT(f, a, e, mgrp4); return;
|
||||||
|
case NET_MGRP6: FIB_INSERT(f, a, e, mgrp6); return;
|
||||||
default: bug("invalid type");
|
default: bug("invalid type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -900,7 +900,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old,
|
|||||||
static inline int
|
static inline int
|
||||||
rte_validate(rte *e)
|
rte_validate(rte *e)
|
||||||
{
|
{
|
||||||
int c;
|
int c, mask;
|
||||||
net *n = e->net;
|
net *n = e->net;
|
||||||
|
|
||||||
// (n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
|
// (n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
|
||||||
@ -911,8 +911,10 @@ rte_validate(rte *e)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mask = net_val_match(n->n.addr->type, NB_MCAST) ? IADDR_MULTICAST : IADDR_HOST;
|
||||||
|
|
||||||
c = net_classify(n->n.addr);
|
c = net_classify(n->n.addr);
|
||||||
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
if ((c < 0) || !(c & mask) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
||||||
{
|
{
|
||||||
log(L_WARN "Ignoring bogus route %N received via %s",
|
log(L_WARN "Ignoring bogus route %N received via %s",
|
||||||
n->n.addr, e->sender->proto->name);
|
n->n.addr, e->sender->proto->name);
|
||||||
@ -1406,6 +1408,13 @@ int
|
|||||||
rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
|
rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
|
||||||
{
|
{
|
||||||
net *n = net_find(t, a);
|
net *n = net_find(t, a);
|
||||||
|
return rt_examine2(n, p, filter, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If rte would be exported to p, call the callback */
|
||||||
|
int
|
||||||
|
rt_examine2(net *n, struct proto *p, struct filter *filter, void (*callback)(struct proto *, void *, rte *), void *data)
|
||||||
|
{
|
||||||
rte *rt = n ? n->routes : NULL;
|
rte *rt = n ? n->routes : NULL;
|
||||||
|
|
||||||
if (!rte_is_valid(rt))
|
if (!rte_is_valid(rt))
|
||||||
@ -1419,6 +1428,9 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
|
|||||||
if (v == RIC_PROCESS)
|
if (v == RIC_PROCESS)
|
||||||
v = (f_run(filter, &rt, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
|
v = (f_run(filter, &rt, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
|
||||||
|
|
||||||
|
if (callback && v > 0)
|
||||||
|
callback(p, data, rt);
|
||||||
|
|
||||||
/* Discard temporary rte */
|
/* Discard temporary rte */
|
||||||
if (rt != n->routes)
|
if (rt != n->routes)
|
||||||
rte_free(rt);
|
rte_free(rt);
|
||||||
@ -1426,6 +1438,32 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
|
|||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
|
|
||||||
return v > 0;
|
return v > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sometimes protocols need to find one route in table without keeping their own copy.
|
||||||
|
* rt_route finds the best route after applying filter.
|
||||||
|
* As the routes may be temporary, successful find is announced by the callback.
|
||||||
|
* Returns 1 if the callback was called.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
rt_route(struct channel *c, net_addr *n, void (*callback)(struct proto *, void *, rte *), void *data)
|
||||||
|
{
|
||||||
|
net *r;
|
||||||
|
|
||||||
|
net_addr *n0 = alloca(n->length);
|
||||||
|
net_copy(n0, n);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
r = net_find(c->table, n0);
|
||||||
|
if (r && rte_is_valid(r->routes) && rt_examine2(r, c->proto, c->out_filter, callback, data))
|
||||||
|
return 1;
|
||||||
|
if (n0->pxlen == 0)
|
||||||
|
return 0;
|
||||||
|
n0->pxlen--;
|
||||||
|
net_normalize(n0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1734,6 +1772,11 @@ rt_preconfig(struct config *c)
|
|||||||
|
|
||||||
rt_new_table(cf_get_symbol("master4"), NET_IP4);
|
rt_new_table(cf_get_symbol("master4"), NET_IP4);
|
||||||
rt_new_table(cf_get_symbol("master6"), NET_IP6);
|
rt_new_table(cf_get_symbol("master6"), NET_IP6);
|
||||||
|
|
||||||
|
rt_new_table(cf_get_symbol("mreq4"), NET_MREQ4);
|
||||||
|
rt_new_table(cf_get_symbol("mreq6"), NET_MREQ6);
|
||||||
|
rt_new_table(cf_get_symbol("mroute4"), NET_MGRP4);
|
||||||
|
rt_new_table(cf_get_symbol("mroute6"), NET_MGRP6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2278,7 +2321,7 @@ if_local_addr(ip_addr a, struct iface *i)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32
|
u32
|
||||||
rt_get_igp_metric(rte *rt)
|
rt_get_igp_metric(rte *rt)
|
||||||
{
|
{
|
||||||
eattr *ea = ea_find(rt->attrs->eattrs, EA_GEN_IGP_METRIC);
|
eattr *ea = ea_find(rt->attrs->eattrs, EA_GEN_IGP_METRIC);
|
||||||
@ -2439,6 +2482,8 @@ rt_format_via(rte *e, byte *via)
|
|||||||
case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
|
case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
|
||||||
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
|
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
|
||||||
case RTD_MULTIPATH: bsprintf(via, "multipath"); break;
|
case RTD_MULTIPATH: bsprintf(via, "multipath"); break;
|
||||||
|
case RTD_MREQUEST: bsprintf(via, "for %s", a->iface->name); break;
|
||||||
|
case RTD_MULTICAST: bsprintf(via, "iifs: %b, oifs: %b", e->u.mkrt.iifs, e->u.mkrt.oifs); break;
|
||||||
default: bsprintf(via, "???");
|
default: bsprintf(via, "???");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,25 @@ sk_set_min_ttl6(sock *s, int ttl)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_set_router_alert4(sock *s, int ra)
|
||||||
|
{
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_ROUTER_ALERT, &ra, sizeof(ra)) < 0)
|
||||||
|
ERR("IP_ROUTER_ALER");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_set_router_alert6(sock *s, int ra)
|
||||||
|
{
|
||||||
|
if (setsockopt(s->fd, SOL_IPV6, IPV6_ROUTER_ALERT, &ra, sizeof(ra)) < 0)
|
||||||
|
ERR("IPV6_ROUTER_ALER");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
sk_disable_mtu_disc4(sock *s)
|
sk_disable_mtu_disc4(sock *s)
|
||||||
{
|
{
|
||||||
|
100
sysdep/unix/io.c
100
sysdep/unix/io.c
@ -122,10 +122,11 @@ tracked_fopen(pool *p, char *name, char *mode)
|
|||||||
#define NEAR_TIMER_LIMIT 4
|
#define NEAR_TIMER_LIMIT 4
|
||||||
|
|
||||||
static list near_timers, far_timers;
|
static list near_timers, far_timers;
|
||||||
static bird_clock_t first_far_timer = TIME_INFINITY;
|
static btime first_far_timer = BTIME_INFINITY;
|
||||||
|
|
||||||
/* now must be different from 0, because 0 is a special value in timer->expires */
|
/* now must be different from 0, because 0 is a special value in timer->expires */
|
||||||
bird_clock_t now = 1, now_real, boot_time;
|
bird_clock_t now = 1, now_real, boot_time;
|
||||||
|
btime now_btime = 1;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_times_plain(void)
|
update_times_plain(void)
|
||||||
@ -134,10 +135,11 @@ update_times_plain(void)
|
|||||||
int delta = new_time - now_real;
|
int delta = new_time - now_real;
|
||||||
|
|
||||||
if ((delta >= 0) && (delta < 60))
|
if ((delta >= 0) && (delta < 60))
|
||||||
now += delta;
|
now_btime += delta S;
|
||||||
else if (now_real != 0)
|
else if (now_real != 0)
|
||||||
log(L_WARN "Time jump, delta %d s", delta);
|
log(L_WARN "Time jump, delta %d s", delta);
|
||||||
|
|
||||||
|
now = now_btime TO_S;
|
||||||
now_real = new_time;
|
now_real = new_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,11 +153,14 @@ update_times_gettime(void)
|
|||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
die("clock_gettime: %m");
|
die("clock_gettime: %m");
|
||||||
|
|
||||||
if (ts.tv_sec != now) {
|
btime bt = (ts.tv_sec S) + (ts.tv_nsec NS);
|
||||||
if (ts.tv_sec < now)
|
|
||||||
|
if (bt != now_btime) {
|
||||||
|
if (bt < now_btime)
|
||||||
log(L_ERR "Monotonic timer is broken");
|
log(L_ERR "Monotonic timer is broken");
|
||||||
|
|
||||||
now = ts.tv_sec;
|
now_btime = bt;
|
||||||
|
now = now_btime TO_S;
|
||||||
now_real = time(NULL);
|
now_real = time(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +239,7 @@ tm_insert_near(timer *t)
|
|||||||
{
|
{
|
||||||
node *n = HEAD(near_timers);
|
node *n = HEAD(near_timers);
|
||||||
|
|
||||||
while (n->next && (SKIP_BACK(timer, n, n)->expires < t->expires))
|
while (n->next && (SKIP_BACK(timer, n, n)->expires_btime < t->expires_btime))
|
||||||
n = n->next;
|
n = n->next;
|
||||||
insert_node(&t->n, n->prev);
|
insert_node(&t->n, n->prev);
|
||||||
}
|
}
|
||||||
@ -259,17 +264,25 @@ tm_insert_near(timer *t)
|
|||||||
void
|
void
|
||||||
tm_start(timer *t, unsigned after)
|
tm_start(timer *t, unsigned after)
|
||||||
{
|
{
|
||||||
bird_clock_t when;
|
|
||||||
|
|
||||||
if (t->randomize)
|
if (t->randomize)
|
||||||
after += random() % (t->randomize + 1);
|
after += random() % (t->randomize + 1);
|
||||||
when = now + after;
|
|
||||||
if (t->expires == when)
|
tm_start_btime(t, after S);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tm_start_btime(timer *t, btime after)
|
||||||
|
{
|
||||||
|
btime when;
|
||||||
|
|
||||||
|
when = now_btime + after;
|
||||||
|
if (t->expires_btime == when)
|
||||||
return;
|
return;
|
||||||
if (t->expires)
|
if (t->expires_btime)
|
||||||
rem_node(&t->n);
|
rem_node(&t->n);
|
||||||
t->expires = when;
|
t->expires_btime = when;
|
||||||
if (after <= NEAR_TIMER_LIMIT)
|
t->expires = when TO_S;
|
||||||
|
if (after TO_S <= NEAR_TIMER_LIMIT)
|
||||||
tm_insert_near(t);
|
tm_insert_near(t);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -289,10 +302,10 @@ tm_start(timer *t, unsigned after)
|
|||||||
void
|
void
|
||||||
tm_stop(timer *t)
|
tm_stop(timer *t)
|
||||||
{
|
{
|
||||||
if (t->expires)
|
if (t->expires_btime)
|
||||||
{
|
{
|
||||||
rem_node(&t->n);
|
rem_node(&t->n);
|
||||||
t->expires = 0;
|
t->expires = t->expires_btime = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,16 +332,16 @@ tm_dump_all(void)
|
|||||||
tm_dump_them("Far", &far_timers);
|
tm_dump_them("Far", &far_timers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline time_t
|
static inline btime
|
||||||
tm_first_shot(void)
|
tm_first_shot(void)
|
||||||
{
|
{
|
||||||
time_t x = first_far_timer;
|
btime x = first_far_timer;
|
||||||
|
|
||||||
if (!EMPTY_LIST(near_timers))
|
if (!EMPTY_LIST(near_timers))
|
||||||
{
|
{
|
||||||
timer *t = SKIP_BACK(timer, n, HEAD(near_timers));
|
timer *t = SKIP_BACK(timer, n, HEAD(near_timers));
|
||||||
if (t->expires < x)
|
if (t->expires_btime < x)
|
||||||
x = t->expires;
|
x = t->expires_btime;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
@ -341,21 +354,21 @@ tm_shot(void)
|
|||||||
timer *t;
|
timer *t;
|
||||||
node *n, *m;
|
node *n, *m;
|
||||||
|
|
||||||
if (first_far_timer <= now)
|
if (first_far_timer <= now_btime)
|
||||||
{
|
{
|
||||||
bird_clock_t limit = now + NEAR_TIMER_LIMIT;
|
btime limit = now_btime + NEAR_TIMER_LIMIT S;
|
||||||
first_far_timer = TIME_INFINITY;
|
first_far_timer = BTIME_INFINITY;
|
||||||
n = HEAD(far_timers);
|
n = HEAD(far_timers);
|
||||||
while (m = n->next)
|
while (m = n->next)
|
||||||
{
|
{
|
||||||
t = SKIP_BACK(timer, n, n);
|
t = SKIP_BACK(timer, n, n);
|
||||||
if (t->expires <= limit)
|
if (t->expires_btime <= limit)
|
||||||
{
|
{
|
||||||
rem_node(n);
|
rem_node(n);
|
||||||
tm_insert_near(t);
|
tm_insert_near(t);
|
||||||
}
|
}
|
||||||
else if (t->expires < first_far_timer)
|
else if (t->expires_btime < first_far_timer)
|
||||||
first_far_timer = t->expires;
|
first_far_timer = t->expires_btime;
|
||||||
n = m;
|
n = m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,17 +376,17 @@ tm_shot(void)
|
|||||||
{
|
{
|
||||||
int delay;
|
int delay;
|
||||||
t = SKIP_BACK(timer, n, n);
|
t = SKIP_BACK(timer, n, n);
|
||||||
if (t->expires > now)
|
if (t->expires_btime > now_btime)
|
||||||
break;
|
break;
|
||||||
rem_node(n);
|
rem_node(n);
|
||||||
delay = t->expires - now;
|
delay = t->expires_btime - now_btime;
|
||||||
t->expires = 0;
|
t->expires = t->expires_btime = 0;
|
||||||
if (t->recurrent)
|
if (t->recurrent)
|
||||||
{
|
{
|
||||||
int i = t->recurrent - delay;
|
int i = t->recurrent S - delay;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i = 0;
|
i = 0;
|
||||||
tm_start(t, i);
|
tm_start_btime(t, i);
|
||||||
}
|
}
|
||||||
io_log_event(t->hook, t->data);
|
io_log_event(t->hook, t->data);
|
||||||
t->hook(t);
|
t->hook(t);
|
||||||
@ -812,7 +825,7 @@ sk_skip_ip_header(byte *pkt, int *len)
|
|||||||
byte *
|
byte *
|
||||||
sk_rx_buffer(sock *s, int *len)
|
sk_rx_buffer(sock *s, int *len)
|
||||||
{
|
{
|
||||||
if (sk_is_ipv4(s) && (s->type == SK_IP))
|
if (sk_is_ipv4(s) && s->type == SK_IP)
|
||||||
return sk_skip_ip_header(s->rbuf, len);
|
return sk_skip_ip_header(s->rbuf, len);
|
||||||
else
|
else
|
||||||
return s->rbuf;
|
return s->rbuf;
|
||||||
@ -948,6 +961,24 @@ sk_set_min_ttl(sock *s, int ttl)
|
|||||||
return sk_set_min_ttl6(s, ttl);
|
return sk_set_min_ttl6(s, ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sk_set_router_alert - set router alert option
|
||||||
|
* @s: socket
|
||||||
|
* @ra: packets with this router alert option value will be passed to the
|
||||||
|
* socket. Negative integer disables.
|
||||||
|
*
|
||||||
|
* Result: 0 for success, -1 for an error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
sk_set_router_alert(sock *s, int ra)
|
||||||
|
{
|
||||||
|
if (sk_is_ipv4(s))
|
||||||
|
return sk_set_router_alert4(s, ra);
|
||||||
|
else
|
||||||
|
return sk_set_router_alert6(s, ra);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/**
|
/**
|
||||||
* sk_set_md5_auth - add / remove MD5 security association for given socket
|
* sk_set_md5_auth - add / remove MD5 security association for given socket
|
||||||
@ -1087,6 +1118,7 @@ sk_free(resource *r)
|
|||||||
current_sock = sk_next(s);
|
current_sock = sk_next(s);
|
||||||
if (s == stored_sock)
|
if (s == stored_sock)
|
||||||
stored_sock = sk_next(s);
|
stored_sock = sk_next(s);
|
||||||
|
if (NODE_VALID(&s->n))
|
||||||
rem_node(&s->n);
|
rem_node(&s->n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2093,7 +2125,7 @@ void
|
|||||||
io_loop(void)
|
io_loop(void)
|
||||||
{
|
{
|
||||||
int poll_tout;
|
int poll_tout;
|
||||||
time_t tout;
|
btime tout;
|
||||||
int nfds, events, pout;
|
int nfds, events, pout;
|
||||||
sock *s;
|
sock *s;
|
||||||
node *n;
|
node *n;
|
||||||
@ -2107,12 +2139,12 @@ io_loop(void)
|
|||||||
timers:
|
timers:
|
||||||
update_times();
|
update_times();
|
||||||
tout = tm_first_shot();
|
tout = tm_first_shot();
|
||||||
if (tout <= now)
|
if (tout <= now_btime)
|
||||||
{
|
{
|
||||||
tm_shot();
|
tm_shot();
|
||||||
goto timers;
|
goto timers;
|
||||||
}
|
}
|
||||||
poll_tout = (events ? 0 : MIN(tout - now, 3)) * 1000; /* Time in milliseconds */
|
poll_tout = (events ? 0 : MIN(tout - now_btime, 3)) TO_MS; /* Time in milliseconds */
|
||||||
|
|
||||||
io_close_event();
|
io_close_event();
|
||||||
|
|
||||||
|
@ -13,6 +13,27 @@
|
|||||||
|
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
|
||||||
|
/* Microsecond time */
|
||||||
|
|
||||||
|
typedef s64 btime;
|
||||||
|
|
||||||
|
#define S_ *1000000
|
||||||
|
#define MS_ *1000
|
||||||
|
#define US_ *1
|
||||||
|
#define NS_ /1000
|
||||||
|
|
||||||
|
#define TO_S /1000000
|
||||||
|
#define TO_MS /1000
|
||||||
|
#define TO_US /1
|
||||||
|
#define TO_NS *1000
|
||||||
|
|
||||||
|
#ifndef PARSER
|
||||||
|
#define S S_
|
||||||
|
#define MS MS_
|
||||||
|
#define US US_
|
||||||
|
#define NS NS_
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef time_t bird_clock_t; /* Use instead of time_t */
|
typedef time_t bird_clock_t; /* Use instead of time_t */
|
||||||
|
|
||||||
typedef struct timer {
|
typedef struct timer {
|
||||||
@ -22,35 +43,59 @@ typedef struct timer {
|
|||||||
unsigned randomize; /* Amount of randomization */
|
unsigned randomize; /* Amount of randomization */
|
||||||
unsigned recurrent; /* Timer recurrence */
|
unsigned recurrent; /* Timer recurrence */
|
||||||
node n; /* Internal link */
|
node n; /* Internal link */
|
||||||
bird_clock_t expires; /* 0=inactive */
|
btime expires_btime; /* 0=inactive */
|
||||||
|
bird_clock_t expires; /* == expires_btime TO_S */
|
||||||
} timer;
|
} timer;
|
||||||
|
|
||||||
timer *tm_new(pool *);
|
timer *tm_new(pool *);
|
||||||
void tm_start(timer *, unsigned after);
|
void tm_start(timer *, unsigned after);
|
||||||
|
void tm_start_btime(timer *, btime after);
|
||||||
void tm_stop(timer *);
|
void tm_stop(timer *);
|
||||||
void tm_dump_all(void);
|
void tm_dump_all(void);
|
||||||
|
|
||||||
extern bird_clock_t now; /* Relative, monotonic time in seconds */
|
extern bird_clock_t now; /* Relative, monotonic time in seconds */
|
||||||
|
extern btime now_btime; /* dtto in microseconds */
|
||||||
extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
|
extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
|
||||||
extern bird_clock_t boot_time;
|
extern bird_clock_t boot_time;
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
tm_active(timer *t)
|
tm_active(timer *t)
|
||||||
{
|
{
|
||||||
return t->expires != 0;
|
return t->expires_btime != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline btime
|
||||||
|
tm_remains_btime(timer *t)
|
||||||
|
{
|
||||||
|
return t->expires_btime ? t->expires_btime - now_btime : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bird_clock_t
|
static inline bird_clock_t
|
||||||
tm_remains(timer *t)
|
tm_remains(timer *t)
|
||||||
{
|
{
|
||||||
return t->expires ? t->expires - now : 0;
|
return tm_remains_btime(t) TO_S;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
tm_start_max_btime(timer *t, btime after)
|
||||||
|
{
|
||||||
|
btime rem = tm_remains_btime(t);
|
||||||
|
tm_start(t, (rem > after) ? rem : after);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
tm_start_min_btime(timer *t, btime after)
|
||||||
|
{
|
||||||
|
btime rem = tm_remains_btime(t);
|
||||||
|
if (!rem || after < rem)
|
||||||
|
tm_start(t, after);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tm_start_max(timer *t, unsigned after)
|
tm_start_max(timer *t, unsigned after)
|
||||||
{
|
{
|
||||||
bird_clock_t rem = tm_remains(t);
|
tm_start_max_btime(t, after S_);
|
||||||
tm_start(t, (rem > after) ? rem : after);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline timer *
|
static inline timer *
|
||||||
@ -87,4 +132,6 @@ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BTIME_INFINITY 0x7fffffffffffffff
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user