0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-10-18 18:08:45 +00:00

Temporary integrated commit (OSPF), unfinished.

This commit is contained in:
Ondrej Zajicek 2012-10-19 16:26:51 +02:00
parent 5aa9d7447c
commit 19e239576f
11 changed files with 302 additions and 305 deletions

View File

@ -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:

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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
};

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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 *

View File

@ -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_ */