mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 02:01:55 +00:00
Temporary integrated commit (OSPF), unfinished.
This commit is contained in:
parent
5aa9d7447c
commit
19e239576f
@ -21,7 +21,9 @@ static list *this_nets;
|
||||
static struct area_net_config *this_pref;
|
||||
static struct ospf_stubnet_config *this_stubnet;
|
||||
|
||||
#ifdef OSPFv2
|
||||
static inline int ospf_cfg_is_v2(void) { return OSPF_CFG->ospf2; }
|
||||
static inline int ospf_cfg_is_v3(void) { return ! OSPF_CFG->ospf2; }
|
||||
|
||||
static void
|
||||
ospf_iface_finish(void)
|
||||
{
|
||||
@ -38,21 +40,6 @@ ospf_iface_finish(void)
|
||||
if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL))
|
||||
log(L_WARN "Password option without authentication option does not make sense");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OSPFv3
|
||||
static void
|
||||
ospf_iface_finish(void)
|
||||
{
|
||||
struct ospf_iface_patt *ip = OSPF_PATT;
|
||||
|
||||
if (ip->deadint == 0)
|
||||
ip->deadint = ip->deadc * ip->helloint;
|
||||
|
||||
if ((ip->autype != OSPF_AUTH_NONE) || (get_passwords() != NULL))
|
||||
cf_error("Authentication not supported in OSPFv3");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ospf_area_finish(void)
|
||||
@ -104,25 +91,23 @@ ospf_proto_finish(void)
|
||||
}
|
||||
|
||||
static inline void
|
||||
check_defcost(int cost)
|
||||
ospf_check_defcost(int cost)
|
||||
{
|
||||
if ((cost <= 0) || (cost >= LSINFINITY))
|
||||
cf_error("Default cost must be in range 1-%d", LSINFINITY-1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_instance_id(unsigned id)
|
||||
ospf_check_auth(void)
|
||||
{
|
||||
#ifdef OSPFv3
|
||||
OSPF_PATT->instance_id = id;
|
||||
#else
|
||||
cf_error("Instance ID requires OSPFv3");
|
||||
#endif
|
||||
if (ospf_cfg_is_v3())
|
||||
cf_error("Authentication not supported in OSPFv3");
|
||||
}
|
||||
|
||||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
|
||||
CF_KEYWORDS(OSPF, OSPF2, OSPF3, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
|
||||
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, COST2, RETRANSMIT)
|
||||
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
|
||||
CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
|
||||
@ -134,16 +119,23 @@ CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL)
|
||||
|
||||
%type <t> opttext
|
||||
%type <ld> lsadb_args
|
||||
%type <i> ospf_proto_key
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
CF_ADDTO(proto, ospf_proto '}' { ospf_proto_finish(); } )
|
||||
|
||||
ospf_proto_start: proto_start OSPF {
|
||||
ospf_proto_key:
|
||||
OSPF2 { $$ = 1; }
|
||||
| OSPF3 { $$ = 0; }
|
||||
;
|
||||
|
||||
ospf_proto_start: proto_start ospf_proto_key {
|
||||
this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), $1);
|
||||
init_list(&OSPF_CFG->area_list);
|
||||
init_list(&OSPF_CFG->vlink_list);
|
||||
OSPF_CFG->tick = OSPF_DEFAULT_TICK;
|
||||
OSPF_CFG->ospf2 = $2;
|
||||
}
|
||||
;
|
||||
|
||||
@ -155,7 +147,7 @@ ospf_proto:
|
||||
ospf_proto_item:
|
||||
proto_item
|
||||
| RFC1583COMPAT bool { OSPF_CFG->rfc1583 = $2; }
|
||||
| ECMP bool { OSPF_CFG->ecmp = $2 ? DEFAULT_ECMP_LIMIT : 0; }
|
||||
| ECMP bool { OSPF_CFG->ecmp = $2 ? OSPF_DEFAULT_ECMP_LIMIT : 0; }
|
||||
| ECMP bool LIMIT expr { OSPF_CFG->ecmp = $2 ? $4 : 0; if ($4 < 0) cf_error("ECMP limit cannot be negative"); }
|
||||
| TICK expr { OSPF_CFG->tick = $2; if($2<=0) cf_error("Tick must be greater than zero"); }
|
||||
| ospf_area
|
||||
@ -189,9 +181,9 @@ ospf_area_item:
|
||||
| NSSA { this_area->type = OPT_N; }
|
||||
| SUMMARY bool { this_area->summary = $2; }
|
||||
| DEFAULT NSSA bool { this_area->default_nssa = $3; }
|
||||
| DEFAULT COST expr { this_area->default_cost = $3; check_defcost($3); }
|
||||
| DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT_EBIT; check_defcost($3); }
|
||||
| STUB COST expr { this_area->default_cost = $3; check_defcost($3); }
|
||||
| DEFAULT COST expr { this_area->default_cost = $3; ospf_check_defcost($3); }
|
||||
| DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT_EBIT; ospf_check_defcost($3); }
|
||||
| STUB COST expr { this_area->default_cost = $3; ospf_check_defcost($3); }
|
||||
| TRANSLATOR bool { this_area->translator = $2; }
|
||||
| TRANSLATOR STABILITY expr { this_area->transint = $3; }
|
||||
| NETWORKS { this_nets = &this_area->net_list; } '{' pref_list '}'
|
||||
@ -243,10 +235,10 @@ ospf_vlink_item:
|
||||
| WAIT expr { OSPF_PATT->waitint = $2 ; }
|
||||
| DEAD expr { OSPF_PATT->deadint = $2 ; if ($2<=1) cf_error("Dead interval must be greater than one"); }
|
||||
| DEAD COUNT expr { OSPF_PATT->deadc = $3 ; if ($3<=1) cf_error("Dead count must be greater than one"); }
|
||||
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
|
||||
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
|
||||
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
|
||||
| password_list
|
||||
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE; }
|
||||
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE; ospf_check_auth(); }
|
||||
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT; ospf_check_auth(); }
|
||||
| password_list { ospf_check_auth(); }
|
||||
;
|
||||
|
||||
ospf_vlink_start: VIRTUAL LINK idval
|
||||
@ -286,7 +278,7 @@ ospf_iface_item:
|
||||
| TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
|
||||
| TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
|
||||
| TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
|
||||
| REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); }
|
||||
| REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (!ospf_cfg_is_v2()) cf_error("Real broadcast option requires OSPFv2"); }
|
||||
| TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
|
||||
| PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); }
|
||||
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
|
||||
@ -294,13 +286,13 @@ ospf_iface_item:
|
||||
| CHECK LINK bool { OSPF_PATT->check_link = $3; }
|
||||
| ECMP WEIGHT expr { OSPF_PATT->ecmp_weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("ECMP weight must be in range 1-256"); }
|
||||
| NEIGHBORS '{' ipa_list '}'
|
||||
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
|
||||
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
|
||||
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
|
||||
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE; }
|
||||
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE; ospf_check_auth(); }
|
||||
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT; ospf_check_auth(); }
|
||||
| RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; }
|
||||
| RX BUFFER NORMAL { OSPF_PATT->rxbuf = OSPF_RXBUF_NORMAL ; }
|
||||
| RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if (($3 < OSPF_RXBUF_MINSIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
|
||||
| password_list
|
||||
| password_list { ospf_check_auth(); }
|
||||
;
|
||||
|
||||
pref_list:
|
||||
@ -376,7 +368,10 @@ ospf_iface_start:
|
||||
|
||||
ospf_instance_id:
|
||||
/* empty */
|
||||
| INSTANCE expr { set_instance_id($2); }
|
||||
| INSTANCE expr {
|
||||
if (ospf_cfg_is_v2()) cf_error("Instance ID requires OSPFv3");
|
||||
OSPF_PATT->instance_id = $2;
|
||||
}
|
||||
;
|
||||
|
||||
ospf_iface_opts:
|
||||
|
@ -505,7 +505,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
else if (ospf_is_v3(po))
|
||||
OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
|
||||
iface->name, ip->instance_id, oa->areaid);
|
||||
else if (ifa->addr->flags & IA_PEER)
|
||||
else if (addr->flags & IA_PEER)
|
||||
OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
|
||||
iface->name, addr->opposite, oa->areaid);
|
||||
else
|
||||
@ -801,16 +801,60 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
}
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
/*
|
||||
* Matching ifaces and addresses to OSPF ifaces/patterns
|
||||
* ospfX_ifa_notify(), ospfX_ifaces_reconfigure()
|
||||
*
|
||||
* This is significantly different in OSPFv2 and OSPFv3.
|
||||
* In OSPFv2, OSPF ifaces are created for each IP prefix (struct ifa)
|
||||
* In OSPFv3, OSPF ifaces are created based on real iface (struct iface),
|
||||
* but there may be several ones with different instance_id
|
||||
*/
|
||||
|
||||
static inline struct ospf_iface_patt *
|
||||
ospf_iface_patt_find(struct ospf_area_config *ac, struct ifa *a)
|
||||
ospf_iface_patt_find2(struct ospf_area_config *ac, struct ifa *a)
|
||||
{
|
||||
return (struct ospf_iface_patt *) iface_patt_find(&ac->patt_list, a->iface, a);
|
||||
}
|
||||
|
||||
struct ospf_iface_patt *
|
||||
ospf_iface_patt_find3(struct ospf_area_config *ac, struct iface *iface, int iid)
|
||||
{
|
||||
struct ospf_iface_patt *pt, *res = NULL;
|
||||
|
||||
WALK_LIST(pt, ac->patt_list)
|
||||
if ((pt->instance_id >= iid) && (iface_patt_match(&pt->i, iface, NULL)) &&
|
||||
(!res || (pt->instance_id < res->instance_id)))
|
||||
res = pt;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct ospf_iface *
|
||||
ospf_iface_find_by_key2(struct ospf_area *oa, struct ifa *a)
|
||||
{
|
||||
struct ospf_iface *ifa;
|
||||
WALK_LIST(ifa, oa->po->iface_list)
|
||||
if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->type != OSPF_IT_VLINK))
|
||||
return ifa;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ospf_iface *
|
||||
ospf_iface_find_by_key3(struct ospf_area *oa, struct ifa *a, int iid)
|
||||
{
|
||||
struct ospf_iface *ifa;
|
||||
WALK_LIST(ifa, oa->po->iface_list)
|
||||
if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->instance_id == iid) && (ifa->type != OSPF_IT_VLINK))
|
||||
return ifa;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||
ospf_ifa_notify2(struct proto *p, unsigned flags, struct ifa *a)
|
||||
{
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
|
||||
@ -828,7 +872,7 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||
WALK_LIST(oa, po->area_list)
|
||||
{
|
||||
struct ospf_iface_patt *ip;
|
||||
if (ip = ospf_iface_patt_find(oa->ac, a))
|
||||
if (ip = ospf_iface_patt_find2(oa->ac, a))
|
||||
{
|
||||
if (!done)
|
||||
ospf_iface_new(oa, a, ip);
|
||||
@ -852,70 +896,8 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||
}
|
||||
}
|
||||
|
||||
static struct ospf_iface *
|
||||
ospf_iface_find_by_key(struct ospf_area *oa, struct ifa *a)
|
||||
{
|
||||
struct ospf_iface *ifa;
|
||||
WALK_LIST(ifa, oa->po->iface_list)
|
||||
if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->type != OSPF_IT_VLINK))
|
||||
return ifa;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
{
|
||||
struct ospf_iface_patt *ip;
|
||||
struct iface *iface;
|
||||
struct ifa *a;
|
||||
|
||||
WALK_LIST(iface, iface_list)
|
||||
WALK_LIST(a, iface->addrs)
|
||||
{
|
||||
if (a->flags & IA_SECONDARY)
|
||||
continue;
|
||||
|
||||
if (a->scope <= SCOPE_LINK)
|
||||
continue;
|
||||
|
||||
if (ip = ospf_iface_patt_find(oa->ac, a))
|
||||
{
|
||||
/* Main inner loop */
|
||||
struct ospf_iface *ifa = ospf_iface_find_by_key(oa, a);
|
||||
if (ifa)
|
||||
{
|
||||
if (ospf_iface_reconfigure(ifa, ip))
|
||||
continue;
|
||||
|
||||
/* Hard restart */
|
||||
ospf_iface_shutdown(ifa);
|
||||
ospf_iface_remove(ifa);
|
||||
}
|
||||
|
||||
ospf_iface_new(oa, a, ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else /* OSPFv3 */
|
||||
|
||||
struct ospf_iface_patt *
|
||||
ospf_iface_patt_find(struct ospf_area_config *ac, struct iface *iface, int iid)
|
||||
{
|
||||
struct ospf_iface_patt *pt, *res = NULL;
|
||||
|
||||
WALK_LIST(pt, ac->patt_list)
|
||||
if ((pt->instance_id >= iid) && (iface_patt_match(&pt->i, iface, NULL)) &&
|
||||
(!res || (pt->instance_id < res->instance_id)))
|
||||
res = pt;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||
ospf_ifa_notify3(struct proto *p, unsigned flags, struct ifa *a)
|
||||
{
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
|
||||
@ -939,7 +921,7 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||
int iid = 0;
|
||||
|
||||
struct ospf_iface_patt *ip;
|
||||
while (ip = ospf_iface_patt_find(oa->ac, a->iface, iid))
|
||||
while (ip = ospf_iface_patt_find3(oa->ac, a->iface, iid))
|
||||
{
|
||||
ospf_iface_new(oa, a, ip);
|
||||
if (ip->instance_id == 0)
|
||||
@ -980,19 +962,44 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||
}
|
||||
}
|
||||
|
||||
static struct ospf_iface *
|
||||
ospf_iface_find_by_key(struct ospf_area *oa, struct ifa *a, int iid)
|
||||
{
|
||||
struct ospf_iface *ifa;
|
||||
WALK_LIST(ifa, oa->po->iface_list)
|
||||
if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->instance_id == iid) && (ifa->type != OSPF_IT_VLINK))
|
||||
return ifa;
|
||||
|
||||
return NULL;
|
||||
static void
|
||||
ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
{
|
||||
struct ospf_iface_patt *ip;
|
||||
struct iface *iface;
|
||||
struct ifa *a;
|
||||
|
||||
WALK_LIST(iface, iface_list)
|
||||
WALK_LIST(a, iface->addrs)
|
||||
{
|
||||
if (a->flags & IA_SECONDARY)
|
||||
continue;
|
||||
|
||||
if (a->scope <= SCOPE_LINK)
|
||||
continue;
|
||||
|
||||
if (ip = ospf_iface_patt_find2(oa->ac, a))
|
||||
{
|
||||
/* Main inner loop */
|
||||
struct ospf_iface *ifa = ospf_iface_find_by_key2(oa, a);
|
||||
if (ifa)
|
||||
{
|
||||
if (ospf_iface_reconfigure(ifa, ip))
|
||||
continue;
|
||||
|
||||
/* Hard restart */
|
||||
ospf_iface_shutdown(ifa);
|
||||
ospf_iface_remove(ifa);
|
||||
}
|
||||
|
||||
ospf_iface_new(oa, a, ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
static void
|
||||
ospf_ifaces_reconfigure3(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
{
|
||||
struct ospf_iface_patt *ip;
|
||||
struct iface *iface;
|
||||
@ -1008,12 +1015,12 @@ ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
continue;
|
||||
|
||||
int iid = 0;
|
||||
while (ip = ospf_iface_patt_find(nac, iface, iid))
|
||||
while (ip = ospf_iface_patt_find3(nac, iface, iid))
|
||||
{
|
||||
iid = ip->instance_id + 1;
|
||||
|
||||
/* Main inner loop */
|
||||
struct ospf_iface *ifa = ospf_iface_find_by_key(oa, a, ip->instance_id);
|
||||
struct ospf_iface *ifa = ospf_iface_find_by_key3(oa, a, ip->instance_id);
|
||||
if (ifa)
|
||||
{
|
||||
if (ospf_iface_reconfigure(ifa, ip))
|
||||
@ -1029,7 +1036,15 @@ ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void
|
||||
ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
{
|
||||
if (ospf_is_v2(oa->po))
|
||||
ospf_ifaces_reconfigure2(oa, nac);
|
||||
else
|
||||
ospf_ifaces_reconfigure3(oa, nac);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
|
||||
|
@ -14,7 +14,8 @@ void ospf_iface_chstate(struct ospf_iface *ifa, u8 state);
|
||||
void ospf_iface_sm(struct ospf_iface *ifa, int event);
|
||||
struct ospf_iface *ospf_iface_find(struct proto_ospf *p, struct iface *what);
|
||||
void ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface);
|
||||
void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
|
||||
void ospf_ifa_notify2(struct proto *p, unsigned flags, struct ifa *a);
|
||||
void ospf_ifa_notify3(struct proto *p, unsigned flags, struct ifa *a);
|
||||
void ospf_iface_info(struct ospf_iface *ifa);
|
||||
void ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip);
|
||||
void ospf_iface_remove(struct ospf_iface *ifa);
|
||||
|
@ -394,7 +394,7 @@ lsa_walk_rt3(struct ospf_lsa_rt_walk *rt)
|
||||
{
|
||||
while (rt->buf >= rt->bufend)
|
||||
{
|
||||
rt->en = ospf_hash_find_rt_next(rt->en);
|
||||
rt->en = ospf_hash_find_rt3_next(rt->en);
|
||||
if (!rt->en)
|
||||
return 0;
|
||||
|
||||
@ -423,7 +423,7 @@ lsa_walk_rt_init(struct proto_ospf *po, struct top_hash_entry *act, struct ospf_
|
||||
if (rt->ospf2)
|
||||
rt->en = act;
|
||||
else
|
||||
rt->en = ospf_hash_find_rt_first(po->gr, act->domain, act->lsa.rt);
|
||||
rt->en = ospf_hash_find_rt3_first(po->gr, act->domain, act->lsa.rt);
|
||||
|
||||
rt->buf = rt->en->lsa_body;
|
||||
rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
|
||||
@ -779,7 +779,7 @@ lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
|
||||
struct top_hash_entry *
|
||||
lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body)
|
||||
{
|
||||
/* LSA can be temporarrily, but body must be mb_allocated. */
|
||||
/* LSA can be temporary, but body must be mb_allocated. */
|
||||
int change = 0;
|
||||
struct top_hash_entry *en;
|
||||
|
||||
@ -790,13 +790,11 @@ lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain,
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((en->lsa.length != lsa->length)
|
||||
#ifdef OSPFv2
|
||||
|| (en->lsa.options != lsa->options)
|
||||
#endif
|
||||
|| (en->lsa.age == LSA_MAXAGE)
|
||||
|| (lsa->age == LSA_MAXAGE)
|
||||
|| memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
|
||||
if ((en->lsa.length != lsa->length) ||
|
||||
(en->lsa.type_raw != lsa->type_raw) || /* check for OSPFv2 options */
|
||||
(en->lsa.age == LSA_MAXAGE) ||
|
||||
(lsa->age == LSA_MAXAGE) ||
|
||||
memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
|
||||
change = 1;
|
||||
|
||||
s_rem_node(SNODE en);
|
||||
|
@ -292,6 +292,7 @@ ospf_dump(struct proto *p)
|
||||
static struct proto *
|
||||
ospf_init(struct proto_config *c)
|
||||
{
|
||||
struct ospf_config *oc = (struct ospf_config *) c;
|
||||
struct proto *p = proto_new(c, sizeof(struct proto_ospf));
|
||||
|
||||
p->make_tmp_attrs = ospf_make_tmp_attrs;
|
||||
@ -301,7 +302,7 @@ ospf_init(struct proto_config *c)
|
||||
p->accept_ra_types = RA_OPTIMAL;
|
||||
p->rt_notify = ospf_rt_notify;
|
||||
p->if_notify = ospf_if_notify;
|
||||
p->ifa_notify = ospf_ifa_notify;
|
||||
p->ifa_notify = oc->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3;
|
||||
p->rte_better = ospf_rte_better;
|
||||
p->rte_same = ospf_rte_same;
|
||||
|
||||
@ -915,14 +916,12 @@ ospf_sh_iface(struct proto *p, char *iff)
|
||||
* values
|
||||
*/
|
||||
|
||||
#ifdef OSPFv3
|
||||
|
||||
static struct ospf_lsa_header *
|
||||
fake_lsa_from_prefix_lsa(struct ospf_lsa_header *dst, struct ospf_lsa_header *src,
|
||||
struct ospf_lsa_prefix *px)
|
||||
{
|
||||
dst->age = src->age;
|
||||
dst->type = px->ref_type;
|
||||
dst->type_raw = px->ref_type;
|
||||
dst->id = px->ref_id;
|
||||
dst->rt = px->ref_rt;
|
||||
dst->sn = src->sn;
|
||||
@ -930,9 +929,8 @@ fake_lsa_from_prefix_lsa(struct ospf_lsa_header *dst, struct ospf_lsa_header *sr
|
||||
return dst;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int lsa_compare_ospf3; // XXXX fixme
|
||||
static int lsa_compare_ospf3;
|
||||
|
||||
static int
|
||||
lsa_compare_for_state(const void *p1, const void *p2)
|
||||
@ -944,27 +942,25 @@ lsa_compare_for_state(const void *p1, const void *p2)
|
||||
struct ospf_lsa_header lsatmp1, lsatmp2;
|
||||
u16 lsa1_type = he1->lsa_type;
|
||||
u16 lsa2_type = he2->lsa_type;
|
||||
int px1 = 0;
|
||||
int px2 = 0;
|
||||
|
||||
if (he1->domain != he2->domain)
|
||||
return he1->domain - he2->domain;
|
||||
|
||||
if (lsa_compare_ospf3)
|
||||
|
||||
/* px1 or px2 assumes OSPFv3 */
|
||||
int px1 = (lsa1_type == LSA_T_PREFIX);
|
||||
int px2 = (lsa2_type == LSA_T_PREFIX);
|
||||
|
||||
if (px1)
|
||||
{
|
||||
px1 = (lsa1_type == LSA_T_PREFIX);
|
||||
px2 = (lsa2_type == LSA_T_PREFIX);
|
||||
xxxx();
|
||||
lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
|
||||
lsa1_type = lsa1->type_raw; /* FIXME: handle unknown ref_type */
|
||||
}
|
||||
|
||||
if (px1)
|
||||
{
|
||||
lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
|
||||
lsa1_type = lsa1->type;
|
||||
px1 = 1;
|
||||
}
|
||||
|
||||
if (px2)
|
||||
lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
|
||||
if (px2)
|
||||
{
|
||||
lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
|
||||
lsa2_type = lsa2->type_raw;
|
||||
}
|
||||
|
||||
|
||||
@ -976,11 +972,9 @@ lsa_compare_for_state(const void *p1, const void *p2)
|
||||
|
||||
if (nt1)
|
||||
{
|
||||
#ifdef OSPFv3
|
||||
/* In OSPFv3, networks are named based on ID of DR */
|
||||
if (lsa1->rt != lsa2->rt)
|
||||
if (lsa_compare_ospf3 && (lsa1->rt != lsa2->rt))
|
||||
return lsa1->rt - lsa2->rt;
|
||||
#endif
|
||||
|
||||
/* For OSPFv2, this is IP of the network,
|
||||
for OSPFv3, this is interface ID */
|
||||
@ -1062,7 +1056,7 @@ show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he, int verbose)
|
||||
if (ospf_is_v2(po))
|
||||
{
|
||||
/* In OSPFv2, we try to find network-LSA to get prefix/pxlen */
|
||||
struct top_hash_entry *net_he = ospf_hash_find_net(po->gr, he->domain, rtl.id, 0);
|
||||
struct top_hash_entry *net_he = ospf_hash_find_net2(po->gr, he->domain, rtl.id);
|
||||
|
||||
if (net_he)
|
||||
{
|
||||
@ -1163,7 +1157,7 @@ show_lsa_external(struct top_hash_entry *he, int ospf2)
|
||||
}
|
||||
|
||||
static inline void
|
||||
show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
|
||||
show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode)
|
||||
{
|
||||
struct ospf_lsa_prefix *px = he->lsa_body;
|
||||
ip_addr pxa;
|
||||
@ -1174,13 +1168,13 @@ show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
|
||||
int i;
|
||||
|
||||
/* We check whether given prefix-LSA is related to the current node */
|
||||
if ((px->ref_type != cnode->type_raw) || (px->ref_rt != cnode->rt))
|
||||
if ((px->ref_type != cnode->lsa.type_raw) || (px->ref_rt != cnode->lsa.rt))
|
||||
return;
|
||||
|
||||
if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
|
||||
return;
|
||||
|
||||
if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->id))
|
||||
if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->lsa.id))
|
||||
return;
|
||||
|
||||
buf = px->rest;
|
||||
@ -1199,7 +1193,6 @@ void
|
||||
ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
{
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
struct ospf_lsa_header *cnode = NULL;
|
||||
int ospf2 = ospf_is_v2(po);
|
||||
int num = po->gr->hash_entries;
|
||||
unsigned int i, ix, j1, j2, jx;
|
||||
@ -1218,6 +1211,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
struct top_hash_entry *hea[num];
|
||||
struct top_hash_entry *hex[verbose ? num : 0];
|
||||
struct top_hash_entry *he;
|
||||
struct top_hash_entry *cnode = NULL;
|
||||
|
||||
j1 = j2 = jx = 0;
|
||||
WALK_SLIST(he, po->lsal)
|
||||
@ -1257,6 +1251,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
if ((j1 + j2) != num)
|
||||
die("Fatal mismatch");
|
||||
|
||||
lsa_compare_ospf3 = !ospf2;
|
||||
qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state);
|
||||
qsort(hex, jx, sizeof(struct top_hash_entry *), ext_compare_for_state);
|
||||
|
||||
@ -1290,7 +1285,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
if (((he->lsa_type == LSA_T_RT) || (he->lsa_type == LSA_T_NET))
|
||||
&& ((he->color == INSPF) || !reachable))
|
||||
{
|
||||
cnode = &(he->lsa);
|
||||
cnode = he;
|
||||
|
||||
if (he->domain != last_area)
|
||||
{
|
||||
@ -1304,12 +1299,12 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->rt));
|
||||
ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->lsa.rt));
|
||||
|
||||
switch (he->lsa_type)
|
||||
{
|
||||
case LSA_T_RT:
|
||||
if (he->lsa.id == cnode->id)
|
||||
if (he->lsa.id == cnode->lsa.id)
|
||||
show_lsa_router(po, he, verbose);
|
||||
break;
|
||||
|
||||
@ -1318,12 +1313,12 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
break;
|
||||
|
||||
case LSA_T_SUM_NET:
|
||||
if (cnode->type == LSA_T_RT)
|
||||
if (cnode->lsa_type == LSA_T_RT)
|
||||
show_lsa_sum_net(he, ospf2);
|
||||
break;
|
||||
|
||||
case LSA_T_SUM_RT:
|
||||
if (cnode->type == LSA_T_RT)
|
||||
if (cnode->lsa_type == LSA_T_RT)
|
||||
show_lsa_sum_rt(he, ospf2);
|
||||
break;
|
||||
|
||||
@ -1340,13 +1335,13 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
/* In these cases, we close the current node */
|
||||
if ((i+1 == j1)
|
||||
|| (hea[i+1]->domain != last_area)
|
||||
|| (hea[i+1]->lsa.rt != cnode->rt)
|
||||
|| (hea[i+1]->lsa.rt != cnode->lsa.rt)
|
||||
|| (hea[i+1]->lsa_type == LSA_T_NET))
|
||||
{
|
||||
while ((ix < jx) && (hex[ix]->lsa.rt < cnode->rt))
|
||||
while ((ix < jx) && (hex[ix]->lsa.rt < cnode->lsa.rt))
|
||||
ix++;
|
||||
|
||||
while ((ix < jx) && (hex[ix]->lsa.rt == cnode->rt))
|
||||
while ((ix < jx) && (hex[ix]->lsa.rt == cnode->lsa.rt))
|
||||
show_lsa_external(hex[ix++], ospf2);
|
||||
|
||||
cnode = NULL;
|
||||
@ -1426,6 +1421,7 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
|
||||
unsigned int i, j;
|
||||
int last_dscope = -1;
|
||||
u32 last_domain = 0;
|
||||
u16 type_mask = ospf_is_v2(po) ? 0x00ff : 0xffff; /* see lsa_get_type() */
|
||||
|
||||
if (p->proto_state != PS_UP)
|
||||
{
|
||||
@ -1452,17 +1448,18 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
|
||||
for (i = 0; i < j; i++)
|
||||
{
|
||||
struct ospf_lsa_header *lsa = &(hea[i]->lsa);
|
||||
int dscope = LSA_SCOPE(hea[i]->lsa_type);
|
||||
|
||||
u16 lsa_type = lsa->type_raw & type_mask;
|
||||
u16 dscope = LSA_SCOPE(hea[i]->lsa_type);
|
||||
|
||||
/* Hack: 1 is used for LSA_SCOPE_LINK, fixed by & 0xf000 */
|
||||
if (ld->scope && (dscope != (ld->scope & 0xf000)))
|
||||
continue;
|
||||
|
||||
if ((ld->scope == LSA_SCOPE_AREA) && (hea[i]->domain != ld->area))
|
||||
continue;
|
||||
|
||||
/* Ignore high nibble */
|
||||
// XXXX check
|
||||
if (ld->type && ((lsa->type & 0x0fff) != (ld->type & 0x0fff)))
|
||||
/* For user convenience ignore high nibble */
|
||||
if (ld->type && ((lsa_type & 0x0fff) != (ld->type & 0x0fff)))
|
||||
continue;
|
||||
|
||||
if (ld->lsid && (lsa->id != ld->lsid))
|
||||
@ -1499,24 +1496,24 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
|
||||
}
|
||||
|
||||
cli_msg(-1017," %04x %-15R %-15R %5u %08x %04x",
|
||||
lsa->type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
|
||||
lsa_type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
|
||||
}
|
||||
cli_msg(0, "");
|
||||
}
|
||||
|
||||
|
||||
struct protocol proto_ospf = {
|
||||
name: "OSPF",
|
||||
template: "ospf%d",
|
||||
attr_class: EAP_OSPF,
|
||||
preference: DEF_PREF_OSPF,
|
||||
init: ospf_init,
|
||||
dump: ospf_dump,
|
||||
start: ospf_start,
|
||||
shutdown: ospf_shutdown,
|
||||
reconfigure: ospf_reconfigure,
|
||||
get_status: ospf_get_status,
|
||||
get_attr: ospf_get_attr,
|
||||
get_route_info: ospf_get_route_info
|
||||
// show_proto_info: ospf_sh
|
||||
.name = "OSPF",
|
||||
.template = "ospf%d",
|
||||
.attr_class = EAP_OSPF,
|
||||
.preference = DEF_PREF_OSPF,
|
||||
.init = ospf_init,
|
||||
.dump = ospf_dump,
|
||||
.start = ospf_start,
|
||||
.shutdown = ospf_shutdown,
|
||||
.reconfigure = ospf_reconfigure,
|
||||
.get_status = ospf_get_status,
|
||||
.get_attr = ospf_get_attr,
|
||||
.get_route_info = ospf_get_route_info
|
||||
};
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
* BIRD -- OSPF
|
||||
*
|
||||
* (c) 1999--2005 Ondrej Filip <feela@network.cz>
|
||||
* (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2009--2012 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
@ -53,13 +55,6 @@ do { if ((po->proto.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
|
||||
|
||||
#define OSPF_PROTO 89
|
||||
|
||||
|
||||
// XXXX
|
||||
#define OSPFv3 1
|
||||
#define OSPF_VERSION 3
|
||||
|
||||
|
||||
|
||||
#define LSREFRESHTIME 1800 /* 30 minutes */
|
||||
#define MINLSINTERVAL 5
|
||||
#define MINLSARRIVAL 1
|
||||
@ -75,9 +70,10 @@ struct ospf_config
|
||||
{
|
||||
struct proto_config c;
|
||||
unsigned tick;
|
||||
byte ospf2;
|
||||
byte rfc1583;
|
||||
byte abr;
|
||||
int ecmp;
|
||||
byte ecmp;
|
||||
list area_list; /* list of struct ospf_area_config */
|
||||
list vlink_list; /* list of struct ospf_iface_patt */
|
||||
};
|
||||
@ -314,16 +310,6 @@ static inline void ospf_pkt_set_instance_id(struct ospf_packet *pkt, u16 val)
|
||||
{ pkt->vdep = htons(val << 8); }
|
||||
|
||||
|
||||
// XXXX
|
||||
/*
|
||||
#define LSA_T_RT 1
|
||||
#define LSA_T_NET 2
|
||||
#define LSA_T_SUM_NET 3
|
||||
#define LSA_T_SUM_RT 4
|
||||
#define LSA_T_EXT 5
|
||||
#define LSA_T_NSSA 7
|
||||
*/
|
||||
|
||||
#define LSA_T_RT 0x2001
|
||||
#define LSA_T_NET 0x2002
|
||||
#define LSA_T_SUM_NET 0x2003
|
||||
@ -524,6 +510,12 @@ lsa_net_count(struct ospf_lsa_header *lsa)
|
||||
/ sizeof(u32);
|
||||
}
|
||||
|
||||
/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
|
||||
as index, so we need to encapsulate RID to IP address */
|
||||
|
||||
#define ipa_from_rid(x) ipa_from_u32(x)
|
||||
#define ipa_to_rid(x) ipa_to_u32(x)
|
||||
|
||||
|
||||
#define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
|
||||
#define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
|
||||
@ -723,6 +715,7 @@ struct proto_ospf
|
||||
list area_list;
|
||||
int areano; /* Number of area I belong to */
|
||||
struct fib rtf; /* Routing table */
|
||||
byte ospf2; /* OSPF v2 or v3 */
|
||||
byte rfc1583; /* RFC1583 compatibility */
|
||||
byte ebit; /* Did I originate any ext lsa? */
|
||||
byte ecmp; /* Maximal number of nexthops in ECMP route, or 0 */
|
||||
@ -776,26 +769,32 @@ void schedule_rtcalc(struct proto_ospf *po);
|
||||
void schedule_net_lsa(struct ospf_iface *ifa);
|
||||
|
||||
static inline int ospf_is_v2(struct proto_ospf *po)
|
||||
{ return 0; } // XXXX fixme
|
||||
{ return po->ospf2; }
|
||||
|
||||
static inline int ospf_is_v3(struct proto_ospf *po)
|
||||
{ return 1; } // XXXX fixme
|
||||
{ return ! po->ospf2; }
|
||||
|
||||
static inline int ospf_get_version(struct proto_ospf *po)
|
||||
{ return ospf_is_v2(po) ? 2 : 3; }
|
||||
|
||||
static inline void lsa_fix_options(struct proto_ospf *po, struct ospf_lsa_header *lsa, u8 options)
|
||||
{ if (ospf_is_v2(po)) lsa_set_options(lsa, options); }
|
||||
|
||||
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
|
||||
|
||||
static inline struct ospf_area *ospf_main_area(struct proto_ospf *po)
|
||||
{ return (po->areano == 1) ? HEAD(po->area_list) : po->backbone; }
|
||||
|
||||
static inline int oa_is_stub(struct ospf_area *oa)
|
||||
{ return (oa->options & (OPT_E | OPT_N)) == 0; }
|
||||
|
||||
static inline int oa_is_ext(struct ospf_area *oa)
|
||||
{ return oa->options & OPT_E; }
|
||||
|
||||
static inline int oa_is_nssa(struct ospf_area *oa)
|
||||
{ return oa->options & OPT_N; }
|
||||
|
||||
|
||||
|
||||
void schedule_link_lsa(struct ospf_iface *ifa); // XXXX caller ??
|
||||
|
||||
void ospf_sh_neigh(struct proto *p, char *iff);
|
||||
|
@ -2,6 +2,8 @@
|
||||
* BIRD -- OSPF
|
||||
*
|
||||
* (c) 1999--2005 Ondrej Filip <feela@network.cz>
|
||||
* (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2009--2012 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
@ -18,7 +20,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
|
||||
|
||||
pkt = (struct ospf_packet *) buf;
|
||||
|
||||
pkt->version = OSPF_VERSION;
|
||||
pkt->version = ospf_get_version(po);
|
||||
|
||||
pkt->type = h_type;
|
||||
|
||||
@ -334,7 +336,7 @@ ospf_rx_hook(sock *sk, int size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pkt->version != OSPF_VERSION)
|
||||
if (pkt->version != ospf_get_version(po))
|
||||
{
|
||||
log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version);
|
||||
return 1;
|
||||
|
@ -21,9 +21,7 @@ void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
|
||||
void ospf_send_to_bdr(struct ospf_iface *ifa);
|
||||
|
||||
static inline void ospf_send_to_all(struct ospf_iface *ifa)
|
||||
{
|
||||
ospf_send_to(ifa, ifa->all_routers);
|
||||
}
|
||||
{ ospf_send_to(ifa, ifa->all_routers); }
|
||||
|
||||
static inline void ospf_send_to_des(struct ospf_iface *ifa)
|
||||
{
|
||||
@ -33,14 +31,22 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa)
|
||||
ospf_send_to_bdr(ifa);
|
||||
}
|
||||
|
||||
static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
|
||||
static inline unsigned ospf_pkt_hdrlen(struct proto_ospf *po)
|
||||
{
|
||||
return ospf_is_v2(po) ?
|
||||
(sizeof(struct ospf_packet) + sizeof(union ospf_auth)) :
|
||||
sizeof(struct ospf_packet);
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
ospf_pkt_bufsize(struct ospf_iface *ifa)
|
||||
|
||||
static inline void * ospf_tx_buffer(struct ospf_iface *ifa)
|
||||
{ return ifa->sk->tbuf; }
|
||||
|
||||
static inline unsigned ospf_pkt_bufsize(struct ospf_iface *ifa)
|
||||
{
|
||||
/* Reserve buffer space for authentication footer */
|
||||
return ifa->sk->tbsize -
|
||||
(ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
|
||||
unsigned res_size = (ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
|
||||
return ifa->sk->tbsize - res_size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
/*
|
||||
* BIRD -- OSPF
|
||||
* BIRD -- OSPF
|
||||
*
|
||||
* (c) 2000--2004 Ondrej Filip <feela@network.cz>
|
||||
* (c) 2000--2004 Ondrej Filip <feela@network.cz>
|
||||
* (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2009--2012 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#include "ospf.h"
|
||||
@ -13,10 +15,6 @@ static void add_cand(list * l, struct top_hash_entry *en,
|
||||
struct ospf_area *oa, int i);
|
||||
static void rt_sync(struct proto_ospf *po);
|
||||
|
||||
/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
|
||||
as index, so we need to encapsulate RID to IP address */
|
||||
|
||||
#define ipa_from_rid(x) ipa_from_u32(x)
|
||||
|
||||
static inline void reset_ri(ort *ort)
|
||||
{
|
||||
|
@ -3,6 +3,8 @@
|
||||
*
|
||||
* (c) 1999 Martin Mares <mj@ucw.cz>
|
||||
* (c) 1999--2004 Ondrej Filip <feela@network.cz>
|
||||
* (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2009--2012 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
@ -24,12 +26,6 @@ void originate_prefix_rt_lsa(struct ospf_area *oa);
|
||||
void originate_prefix_net_lsa(struct ospf_iface *ifa);
|
||||
void flush_prefix_net_lsa(struct ospf_iface *ifa);
|
||||
|
||||
#ifdef OSPFv2
|
||||
#define ipa_to_rid(x) _I(x)
|
||||
#else /* OSPFv3 */
|
||||
#define ipa_to_rid(x) _I3(x)
|
||||
#endif
|
||||
|
||||
|
||||
static inline u32
|
||||
fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
|
||||
@ -75,7 +71,7 @@ fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
|
||||
if (ospf_is_v3(po))
|
||||
return fn->uid;
|
||||
|
||||
u32 id = _I(fn->prefix);
|
||||
u32 id = ipa_to_u32(fn->prefix);
|
||||
|
||||
if ((po->rfc1583) || (fn->pxlen == 0) || (fn->pxlen == 32))
|
||||
return id;
|
||||
@ -760,7 +756,6 @@ originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric)
|
||||
OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)",
|
||||
fn->prefix, fn->pxlen, metric);
|
||||
|
||||
/* options argument is used in ORT_NET and OSPFv3 only */
|
||||
lsa.age = 0;
|
||||
lsa.type_raw = LSA_T_SUM_NET;
|
||||
lsa.id = fibnode_to_lsaid(po, fn);
|
||||
@ -999,24 +994,10 @@ find_surrogate_fwaddr(struct ospf_area *oa)
|
||||
(ifa->type == OSPF_IT_VLINK))
|
||||
continue;
|
||||
|
||||
#ifdef OSPFv2
|
||||
a = ifa->addr;
|
||||
if (a->flags & IA_PEER)
|
||||
continue;
|
||||
|
||||
np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
|
||||
if (np > cur_np)
|
||||
if (ospf_is_v2(po))
|
||||
{
|
||||
cur_addr = a;
|
||||
cur_np = np;
|
||||
}
|
||||
|
||||
#else /* OSPFv3 */
|
||||
WALK_LIST(a, ifa->iface->addrs)
|
||||
{
|
||||
if ((a->flags & IA_SECONDARY) ||
|
||||
(a->flags & IA_PEER) ||
|
||||
(a->scope <= SCOPE_LINK))
|
||||
a = ifa->addr;
|
||||
if (a->flags & IA_PEER)
|
||||
continue;
|
||||
|
||||
np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
|
||||
@ -1026,7 +1007,23 @@ find_surrogate_fwaddr(struct ospf_area *oa)
|
||||
cur_np = np;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else /* OSPFv3 */
|
||||
{
|
||||
WALK_LIST(a, ifa->iface->addrs)
|
||||
{
|
||||
if ((a->flags & IA_SECONDARY) ||
|
||||
(a->flags & IA_PEER) ||
|
||||
(a->scope <= SCOPE_LINK))
|
||||
continue;
|
||||
|
||||
np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
|
||||
if (np > cur_np)
|
||||
{
|
||||
cur_addr = a;
|
||||
cur_np = np;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cur_addr ? cur_addr->ip : IPA_NONE;
|
||||
@ -1637,71 +1634,66 @@ ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
/* In OSPFv2, sometimes we don't know Router ID when looking for network LSAs.
|
||||
There should be just one, so we find any match. */
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif)
|
||||
{
|
||||
struct top_hash_entry *e;
|
||||
e = f->hash_table[ospf_top_hash(f, domain, id, 0, LSA_T_NET)];
|
||||
|
||||
while (e && (e->lsa.id != id || e->lsa.type != LSA_T_NET || e->domain != domain))
|
||||
e = e->next;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OSPFv3
|
||||
|
||||
/* In OSPFv3, usually we don't know LSA ID when looking for router
|
||||
LSAs. We return matching LSA with smallest LSA ID. */
|
||||
/* In OSPFv2, lsa.id is the same as lsa.rt for router LSA. In OSPFv3, we don't know
|
||||
lsa.id when looking for router LSAs. We return matching LSA with smallest lsa.id. */
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
|
||||
{
|
||||
struct top_hash_entry *rv = NULL;
|
||||
struct top_hash_entry *e;
|
||||
e = f->hash_table[ospf_top_hash(f, domain, 0, rtr, LSA_T_RT)];
|
||||
|
||||
/* We can put rtr for lsa.id to hash fn, it is ignored in OSPFv3 */
|
||||
e = f->hash_table[ospf_top_hash(f, domain, rtr, rtr, LSA_T_RT)];
|
||||
|
||||
while (e)
|
||||
{
|
||||
if (e->lsa.rt == rtr && e->lsa_type == LSA_T_RT && e->domain == domain)
|
||||
{
|
||||
if (e->lsa.rt == rtr && e->lsa.type == LSA_T_RT && e->domain == domain)
|
||||
if (!rv || e->lsa.id < rv->lsa.id)
|
||||
rv = e;
|
||||
e = e->next;
|
||||
if (f->ospf2 && (e->lsa.id == rtr))
|
||||
return e;
|
||||
if (!f->ospf2 && (!rv || e->lsa.id < rv->lsa.id))
|
||||
rv = e;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline struct top_hash_entry *
|
||||
find_matching_rt(struct top_hash_entry *e, u32 domain, u32 rtr)
|
||||
find_matching_rt3(struct top_hash_entry *e, u32 domain, u32 rtr)
|
||||
{
|
||||
while (e && (e->lsa.rt != rtr || e->lsa.type != LSA_T_RT || e->domain != domain))
|
||||
while (e && (e->lsa.rt != rtr || e->lsa_type != LSA_T_RT || e->domain != domain))
|
||||
e = e->next;
|
||||
return e;
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find_rt_first(struct top_graph *f, u32 domain, u32 rtr)
|
||||
ospf_hash_find_rt3_first(struct top_graph *f, u32 domain, u32 rtr)
|
||||
{
|
||||
struct top_hash_entry *e;
|
||||
e = f->hash_table[ospf_top_hash(f, domain, 0, rtr, LSA_T_RT)];
|
||||
return find_matching_rt(e, domain, rtr);
|
||||
return find_matching_rt3(e, domain, rtr);
|
||||
}
|
||||
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find_rt_next(struct top_hash_entry *e)
|
||||
ospf_hash_find_rt3_next(struct top_hash_entry *e)
|
||||
{
|
||||
return find_matching_rt(e->next, e->domain, e->lsa.rt);
|
||||
return find_matching_rt3(e->next, e->domain, e->lsa.rt);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* In OSPFv2, we don't know Router ID when looking for network LSAs.
|
||||
There should be just one, so we find any match. */
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find_net2(struct top_graph *f, u32 domain, u32 id)
|
||||
{
|
||||
struct top_hash_entry *e;
|
||||
e = f->hash_table[ospf_top_hash(f, domain, id, 0, LSA_T_NET)];
|
||||
|
||||
while (e && (e->lsa.id != id || e->lsa_type != LSA_T_NET || e->domain != domain))
|
||||
e = e->next;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
struct top_hash_entry *
|
||||
|
@ -39,6 +39,7 @@ struct top_graph
|
||||
pool *pool; /* Pool we allocate from */
|
||||
slab *hash_slab; /* Slab for hash entries */
|
||||
struct top_hash_entry **hash_table; /* Hashing (modelled a`la fib) */
|
||||
unsigned int ospf2; /* Whether it is for OSPFv2 or OSPFv3 */
|
||||
unsigned int hash_size;
|
||||
unsigned int hash_order;
|
||||
unsigned int hash_mask;
|
||||
@ -71,28 +72,21 @@ void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
|
||||
void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
|
||||
void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src);
|
||||
|
||||
struct top_hash_entry * ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr);
|
||||
struct top_hash_entry * ospf_hash_find_rt3_first(struct top_graph *f, u32 domain, u32 rtr);
|
||||
struct top_hash_entry * ospf_hash_find_rt3_next(struct top_hash_entry *e);
|
||||
|
||||
#ifdef OSPFv2
|
||||
struct top_hash_entry * ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif);
|
||||
struct top_hash_entry * ospf_hash_find_net2(struct top_graph *f, u32 domain, u32 id);
|
||||
|
||||
static inline struct top_hash_entry *
|
||||
ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
|
||||
{
|
||||
return ospf_hash_find(f, domain, rtr, rtr, LSA_T_RT);
|
||||
}
|
||||
|
||||
#else /* OSPFv3 */
|
||||
/* In OSPFv2, id is network IP prefix (lsa.id) while lsa.rt field is unknown
|
||||
In OSPFv3, id is lsa.rt of DR while nif is neighbor iface id (lsa.id) */
|
||||
static inline struct top_hash_entry *
|
||||
ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif)
|
||||
{
|
||||
return ospf_hash_find(f, domain, nif, id, LSA_T_NET);
|
||||
return f->ospf2 ?
|
||||
ospf_hash_find_net2(f, domain, id) :
|
||||
ospf_hash_find(f, domain, nif, id, LSA_T_NET);
|
||||
}
|
||||
|
||||
|
||||
struct top_hash_entry * ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr);
|
||||
struct top_hash_entry * ospf_hash_find_rt_first(struct top_graph *f, u32 domain, u32 rtr);
|
||||
struct top_hash_entry * ospf_hash_find_rt_next(struct top_hash_entry *e);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _BIRD_OSPF_TOPOLOGY_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user