Temporary OSPFv3 development commit.
Finally, it is working.
This commit is contained in:
parent
f9c799a00e
commit
be86240662
12 changed files with 135 additions and 63 deletions
|
@ -54,6 +54,7 @@ typedef u32 ip_addr;
|
||||||
#define ipa_hton(x) x = _MI(htonl(_I(x)))
|
#define ipa_hton(x) x = _MI(htonl(_I(x)))
|
||||||
#define ipa_ntoh(x) x = _MI(ntohl(_I(x)))
|
#define ipa_ntoh(x) x = _MI(ntohl(_I(x)))
|
||||||
#define ipa_classify(x) ipv4_classify(_I(x))
|
#define ipa_classify(x) ipv4_classify(_I(x))
|
||||||
|
#define ipa_has_link_scope(x) ipv4_has_link_scope(_I(x))
|
||||||
#define ipa_opposite(x,len) _MI(_I(x) ^ (len == 30 ? 3 : 1))
|
#define ipa_opposite(x,len) _MI(_I(x) ^ (len == 30 ? 3 : 1))
|
||||||
#define ipa_class_mask(x) _MI(ipv4_class_mask(_I(x)))
|
#define ipa_class_mask(x) _MI(ipv4_class_mask(_I(x)))
|
||||||
#define ipa_from_u32(x) _MI(x)
|
#define ipa_from_u32(x) _MI(x)
|
||||||
|
@ -69,6 +70,11 @@ int ipv4_classify(u32);
|
||||||
u32 ipv4_class_mask(u32);
|
u32 ipv4_class_mask(u32);
|
||||||
byte *ipv4_skip_header(byte *, int *);
|
byte *ipv4_skip_header(byte *, int *);
|
||||||
|
|
||||||
|
static inline int ipv4_has_link_scope(u32 a)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned ipv4_hash(u32 a)
|
static inline unsigned ipv4_hash(u32 a)
|
||||||
{
|
{
|
||||||
/* Returns a 16-bit value */
|
/* Returns a 16-bit value */
|
||||||
|
|
|
@ -60,6 +60,7 @@ typedef struct ipv6_addr {
|
||||||
#define ipa_hton(x) ipv6_hton(&(x))
|
#define ipa_hton(x) ipv6_hton(&(x))
|
||||||
#define ipa_ntoh(x) ipv6_ntoh(&(x))
|
#define ipa_ntoh(x) ipv6_ntoh(&(x))
|
||||||
#define ipa_classify(x) ipv6_classify(&(x))
|
#define ipa_classify(x) ipv6_classify(&(x))
|
||||||
|
#define ipa_has_link_scope(x) ipv6_has_link_scope(&(x))
|
||||||
/* ipa_opposite and ipa_class_mask don't make sense with IPv6 */
|
/* ipa_opposite and ipa_class_mask don't make sense with IPv6 */
|
||||||
/* ipa_from_u32 and ipa_to_u32 replaced by ipa_build */
|
/* ipa_from_u32 and ipa_to_u32 replaced by ipa_build */
|
||||||
#define ipa_build(a,b,c,d) _MI(a,b,c,d)
|
#define ipa_build(a,b,c,d) _MI(a,b,c,d)
|
||||||
|
@ -81,6 +82,11 @@ int ipv6_compare(ip_addr, ip_addr);
|
||||||
int ipv4_pton_u32(char *, u32 *);
|
int ipv4_pton_u32(char *, u32 *);
|
||||||
void ipv6_absolutize(ip_addr *, ip_addr *);
|
void ipv6_absolutize(ip_addr *, ip_addr *);
|
||||||
|
|
||||||
|
static inline int ipv6_has_link_scope(ip_addr *a)
|
||||||
|
{
|
||||||
|
return ((a->addr[0] & 0xffc00000) == 0xfe800000);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This hash function looks well, but once IPv6 enters
|
* This hash function looks well, but once IPv6 enters
|
||||||
* mainstream use, we need to check that it has good
|
* mainstream use, we need to check that it has good
|
||||||
|
|
|
@ -99,6 +99,7 @@ typedef struct neighbor {
|
||||||
#define NEF_STICKY 1
|
#define NEF_STICKY 1
|
||||||
|
|
||||||
neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags);
|
neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags);
|
||||||
|
neighbor *neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags);
|
||||||
|
|
||||||
static inline int neigh_connected_to(struct proto *p, ip_addr *a, struct iface *i)
|
static inline int neigh_connected_to(struct proto *p, ip_addr *a, struct iface *i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -100,21 +100,21 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
|
||||||
* IP address, neigh_find() returns %NULL.
|
* IP address, neigh_find() returns %NULL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
neighbor *
|
neighbor *
|
||||||
neigh_find(struct proto *p, ip_addr *a, unsigned flags)
|
neigh_find(struct proto *p, ip_addr *a, unsigned flags)
|
||||||
{
|
{
|
||||||
return neigh_find2(p, a, NULL, flags);
|
return neigh_find2(p, a, NULL, flags);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
neighbor *
|
neighbor *
|
||||||
neigh_find(struct proto *p, ip_addr *a, unsigned flags)
|
neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
||||||
{
|
{
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
int class, scope = SCOPE_HOST;
|
int class, scope = SCOPE_HOST;
|
||||||
unsigned int h = neigh_hash(p, a);
|
unsigned int h = neigh_hash(p, a);
|
||||||
struct iface *i, *j;
|
struct iface *i;
|
||||||
|
|
||||||
WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */
|
WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */
|
||||||
if (n->proto == p && ipa_equal(*a, n->addr))
|
if (n->proto == p && ipa_equal(*a, n->addr))
|
||||||
|
@ -123,27 +123,31 @@ neigh_find(struct proto *p, ip_addr *a, unsigned flags)
|
||||||
class = ipa_classify(*a);
|
class = ipa_classify(*a);
|
||||||
if (class < 0) /* Invalid address */
|
if (class < 0) /* Invalid address */
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((class & IADDR_SCOPE_MASK) < SCOPE_SITE ||
|
if (((class & IADDR_SCOPE_MASK) == SCOPE_HOST) ||
|
||||||
|
(((class & IADDR_SCOPE_MASK) == SCOPE_LINK) && (ifa == NULL)) ||
|
||||||
!(class & IADDR_HOST))
|
!(class & IADDR_HOST))
|
||||||
return NULL; /* Bad scope or a somecast */
|
return NULL; /* Bad scope or a somecast */
|
||||||
|
|
||||||
j = NULL;
|
if (ifa)
|
||||||
|
scope = if_connected(a, ifa);
|
||||||
|
else
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, iface_list)
|
||||||
if ((scope = if_connected(a, i)) >= 0)
|
if ((scope = if_connected(a, i)) >= 0)
|
||||||
{
|
{
|
||||||
j = i;
|
ifa = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!j && !(flags & NEF_STICKY))
|
|
||||||
|
if (!ifa && !(flags & NEF_STICKY))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
n = sl_alloc(neigh_slab);
|
n = sl_alloc(neigh_slab);
|
||||||
n->addr = *a;
|
n->addr = *a;
|
||||||
n->iface = j;
|
n->iface = ifa;
|
||||||
if (j)
|
if (ifa)
|
||||||
{
|
{
|
||||||
add_tail(&neigh_hash_table[h], &n->n);
|
add_tail(&neigh_hash_table[h], &n->n);
|
||||||
add_tail(&j->neighbors, &n->if_n);
|
add_tail(&ifa->neighbors, &n->if_n);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -381,6 +381,7 @@ ospf_iface_add(struct object_lock *lock)
|
||||||
|
|
||||||
ifa->state = OSPF_IS_DOWN;
|
ifa->state = OSPF_IS_DOWN;
|
||||||
ospf_iface_sm(ifa, ISM_UP);
|
ospf_iface_sm(ifa, ISM_UP);
|
||||||
|
schedule_link_lsa(ifa);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -462,9 +462,7 @@ lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain,
|
||||||
en->ini_age = en->lsa.age;
|
en->ini_age = en->lsa.age;
|
||||||
|
|
||||||
if (change)
|
if (change)
|
||||||
{
|
|
||||||
schedule_rtcalc(po);
|
schedule_rtcalc(po);
|
||||||
}
|
|
||||||
|
|
||||||
return en;
|
return en;
|
||||||
}
|
}
|
||||||
|
|
|
@ -627,6 +627,13 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||||
lsadb = lsa_install_new(po, &lsatmp, domain, body);
|
lsadb = lsa_install_new(po, &lsatmp, domain, body);
|
||||||
DBG("New LSA installed in DB\n");
|
DBG("New LSA installed in DB\n");
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
/* Events 6,7 from 4.4.3. */
|
||||||
|
if ((lsatmp.type == LSA_T_LINK) &&
|
||||||
|
(ifa->state == OSPF_IS_DR))
|
||||||
|
schedule_net_lsa(ifa);
|
||||||
|
#endif
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -307,15 +307,29 @@ ospf_build_attrs(ea_list * next, struct linpool *pool, u32 m1, u32 m2,
|
||||||
void
|
void
|
||||||
schedule_net_lsa(struct ospf_iface *ifa)
|
schedule_net_lsa(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
|
struct proto *p = &ifa->oa->po->proto;
|
||||||
|
|
||||||
|
OSPF_TRACE(D_EVENTS, "Scheduling network-LSA origination for iface %s", ifa->iface->name);
|
||||||
ifa->orignet = 1;
|
ifa->orignet = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
void
|
||||||
|
schedule_link_lsa(struct ospf_iface *ifa)
|
||||||
|
{
|
||||||
|
struct proto *p = &ifa->oa->po->proto;
|
||||||
|
|
||||||
|
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->iface->name);
|
||||||
|
ifa->origlink = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
schedule_rt_lsa(struct ospf_area *oa)
|
schedule_rt_lsa(struct ospf_area *oa)
|
||||||
{
|
{
|
||||||
struct proto *p = &oa->po->proto;
|
struct proto *p = &oa->po->proto;
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Scheduling RT lsa origination for area %R.", oa->areaid);
|
OSPF_TRACE(D_EVENTS, "Scheduling router-LSA origination for area %R", oa->areaid);
|
||||||
oa->origrt = 1;
|
oa->origrt = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +341,7 @@ schedule_rtcalc(struct proto_ospf *po)
|
||||||
if (po->calcrt)
|
if (po->calcrt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Scheduling RT calculation.");
|
OSPF_TRACE(D_EVENTS, "Scheduling routing table calculation");
|
||||||
po->calcrt = 1;
|
po->calcrt = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +367,7 @@ area_disp(struct ospf_area *oa)
|
||||||
WALK_LIST(ifa, po->iface_list)
|
WALK_LIST(ifa, po->iface_list)
|
||||||
{
|
{
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
|
/* Link LSA should be originated before Network LSA */
|
||||||
if (ifa->origlink && (ifa->oa == oa))
|
if (ifa->origlink && (ifa->oa == oa))
|
||||||
update_link_lsa(ifa);
|
update_link_lsa(ifa);
|
||||||
#endif
|
#endif
|
||||||
|
@ -478,6 +493,7 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||||
if (ifa->iface == a->iface)
|
if (ifa->iface == a->iface)
|
||||||
{
|
{
|
||||||
schedule_rt_lsa(ifa->oa);
|
schedule_rt_lsa(ifa->oa);
|
||||||
|
schedule_link_lsa(ifa);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,8 +232,8 @@ struct ospf_iface
|
||||||
struct top_hash_entry *net_lsa; /* Originated network LSA */
|
struct top_hash_entry *net_lsa; /* Originated network LSA */
|
||||||
int orignet; /* Schedule network LSA origination */
|
int orignet; /* Schedule network LSA origination */
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
struct top_hash_entry *link_lsa; /* Originated link LSA */
|
|
||||||
int origlink; /* Schedule link LSA origination */
|
int origlink; /* Schedule link LSA origination */
|
||||||
|
struct top_hash_entry *link_lsa; /* Originated link LSA */
|
||||||
struct top_hash_entry *pxn_lsa; /* Originated prefix LSA */
|
struct top_hash_entry *pxn_lsa; /* Originated prefix LSA */
|
||||||
#endif
|
#endif
|
||||||
int fadj; /* Number of full adjacent neigh */
|
int fadj; /* Number of full adjacent neigh */
|
||||||
|
@ -734,6 +734,13 @@ void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs);
|
||||||
void schedule_rt_lsa(struct ospf_area *oa);
|
void schedule_rt_lsa(struct ospf_area *oa);
|
||||||
void schedule_rtcalc(struct proto_ospf *po);
|
void schedule_rtcalc(struct proto_ospf *po);
|
||||||
void schedule_net_lsa(struct ospf_iface *ifa);
|
void schedule_net_lsa(struct ospf_iface *ifa);
|
||||||
|
|
||||||
|
#ifdef OSPFv3
|
||||||
|
void schedule_link_lsa(struct ospf_iface *ifa);
|
||||||
|
#else
|
||||||
|
static inline void schedule_link_lsa(struct ospf_iface *ifa) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ospf_sh_neigh(struct proto *p, char *iff);
|
void ospf_sh_neigh(struct proto *p, char *iff);
|
||||||
void ospf_sh(struct proto *p);
|
void ospf_sh(struct proto *p);
|
||||||
void ospf_sh_iface(struct proto *p, char *iff);
|
void ospf_sh_iface(struct proto *p, char *iff);
|
||||||
|
|
|
@ -321,7 +321,6 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
}
|
}
|
||||||
|
|
||||||
rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||||
DBG(" Number of links: %u\n", rt->links);
|
|
||||||
for (i = 0; i < lsa_rt_count(&act->lsa); i++)
|
for (i = 0; i < lsa_rt_count(&act->lsa); i++)
|
||||||
{
|
{
|
||||||
tmp = NULL;
|
tmp = NULL;
|
||||||
|
@ -1178,7 +1177,7 @@ again1:
|
||||||
if (nf->n.ifa) a0.iface = nf->n.ifa->iface;
|
if (nf->n.ifa) a0.iface = nf->n.ifa->iface;
|
||||||
a0.gw = nf->n.nh;
|
a0.gw = nf->n.nh;
|
||||||
|
|
||||||
if ((!ipa_equal(nf->n.nh, IPA_NONE)) && (!neigh_find(p, &nf->n.nh, 0)))
|
if (ipa_nonzero(nf->n.nh) && (!neigh_find2(p, &nf->n.nh, nf->n.ifa->iface, 0)))
|
||||||
{
|
{
|
||||||
int found = 0;
|
int found = 0;
|
||||||
struct ospf_iface *ifa;
|
struct ospf_iface *ifa;
|
||||||
|
|
|
@ -168,9 +168,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
struct ospf_lsa_rt_link *ln;
|
struct ospf_lsa_rt_link *ln;
|
||||||
struct ospf_neighbor *neigh;
|
struct ospf_neighbor *neigh;
|
||||||
|
|
||||||
DBG("%s: Originating RT_lsa body for area %R.\n", po->proto.name,
|
|
||||||
oa->areaid);
|
|
||||||
|
|
||||||
ASSERT(po->lsab_used == 0);
|
ASSERT(po->lsab_used == 0);
|
||||||
rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
|
rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
|
||||||
|
|
||||||
|
@ -322,9 +319,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
struct ospf_lsa_rt *rt;
|
struct ospf_lsa_rt *rt;
|
||||||
struct ospf_neighbor *neigh;
|
struct ospf_neighbor *neigh;
|
||||||
|
|
||||||
DBG("%s: Originating RT_lsa body for area %R.\n", po->proto.name,
|
|
||||||
oa->areaid);
|
|
||||||
|
|
||||||
ASSERT(po->lsab_used == 0);
|
ASSERT(po->lsab_used == 0);
|
||||||
rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
|
rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
|
||||||
|
|
||||||
|
@ -411,7 +405,7 @@ originate_rt_lsa(struct ospf_area *oa)
|
||||||
u32 rid = po->proto.cf->global->router_id;
|
u32 rid = po->proto.cf->global->router_id;
|
||||||
void *body;
|
void *body;
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Originating RT_lsa for area %R.", oa->areaid);
|
OSPF_TRACE(D_EVENTS, "Originating router-LSA for area %R", oa->areaid);
|
||||||
|
|
||||||
lsa.age = 0;
|
lsa.age = 0;
|
||||||
lsa.type = LSA_T_RT;
|
lsa.type = LSA_T_RT;
|
||||||
|
@ -522,7 +516,7 @@ originate_net_lsa(struct ospf_iface *ifa)
|
||||||
struct proto *p = &po->proto;
|
struct proto *p = &po->proto;
|
||||||
void *body;
|
void *body;
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Originating Net lsa for iface \"%s\".",
|
OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s",
|
||||||
ifa->iface->name);
|
ifa->iface->name);
|
||||||
|
|
||||||
lsa.age = 0;
|
lsa.age = 0;
|
||||||
|
@ -554,7 +548,7 @@ flush_net_lsa(struct ospf_iface *ifa)
|
||||||
if (ifa->net_lsa == NULL)
|
if (ifa->net_lsa == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Deleting Net lsa for iface \"%s\".",
|
OSPF_TRACE(D_EVENTS, "Flushing network-LSA for iface %s",
|
||||||
ifa->iface->name);
|
ifa->iface->name);
|
||||||
ifa->net_lsa->lsa.sn += 1;
|
ifa->net_lsa->lsa.sn += 1;
|
||||||
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
||||||
|
@ -685,14 +679,14 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
|
||||||
|
|
||||||
if (type == ORT_NET)
|
if (type == ORT_NET)
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_EVENTS, "Originating Net-Summary-LSA for %I/%d (metric %d).",
|
OSPF_TRACE(D_EVENTS, "Originating summary-LSA for %I/%d (metric %d)",
|
||||||
fn->prefix, fn->pxlen, metric);
|
fn->prefix, fn->pxlen, metric);
|
||||||
|
|
||||||
body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
|
body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OSPF_TRACE(D_EVENTS, "Originating RT-Summary-LSA for %R (metric %d).",
|
OSPF_TRACE(D_EVENTS, "Originating summary-LSA for %R (metric %d)",
|
||||||
lsa.id, metric);
|
lsa.id, metric);
|
||||||
|
|
||||||
body = originate_sum_rt_lsa_body(po, &lsa.length, lsa.id, metric, options);
|
body = originate_sum_rt_lsa_body(po, &lsa.length, lsa.id, metric, options);
|
||||||
|
@ -734,7 +728,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
|
||||||
en->lsa.sn = LSA_MAXSEQNO;
|
en->lsa.sn = LSA_MAXSEQNO;
|
||||||
lsasum_calculate(&en->lsa, sum);
|
lsasum_calculate(&en->lsa, sum);
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Flushing summary lsa. (id=%R, type=%d)",
|
OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%d)",
|
||||||
en->lsa.id, en->lsa.type);
|
en->lsa.id, en->lsa.type);
|
||||||
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, oa->areaid, 1);
|
ospf_lsupd_flood(po, NULL, NULL, &en->lsa, oa->areaid, 1);
|
||||||
if (can_flush_lsa(po)) flush_lsa(en, po);
|
if (can_flush_lsa(po)) flush_lsa(en, po);
|
||||||
|
@ -879,15 +873,15 @@ void
|
||||||
originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
||||||
struct ea_list *attrs)
|
struct ea_list *attrs)
|
||||||
{
|
{
|
||||||
|
struct proto *p = &po->proto;
|
||||||
struct ospf_lsa_header lsa;
|
struct ospf_lsa_header lsa;
|
||||||
u32 rid = po->proto.cf->global->router_id;
|
u32 rid = po->proto.cf->global->router_id;
|
||||||
struct top_hash_entry *en = NULL;
|
struct top_hash_entry *en = NULL;
|
||||||
void *body;
|
void *body;
|
||||||
struct proto *p = &po->proto;
|
|
||||||
struct ospf_area *oa;
|
struct ospf_area *oa;
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix,
|
OSPF_TRACE(D_EVENTS, "Originating AS-external-LSA for %I/%d",
|
||||||
n->n.pxlen);
|
n->n.prefix, n->n.pxlen);
|
||||||
|
|
||||||
lsa.age = 0;
|
lsa.age = 0;
|
||||||
lsa.type = LSA_T_EXT;
|
lsa.type = LSA_T_EXT;
|
||||||
|
@ -924,10 +918,14 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
|
||||||
void
|
void
|
||||||
flush_ext_lsa(net *n, struct proto_ospf *po)
|
flush_ext_lsa(net *n, struct proto_ospf *po)
|
||||||
{
|
{
|
||||||
|
struct proto *p = &po->proto;
|
||||||
u32 rid = po->proto.cf->global->router_id;
|
u32 rid = po->proto.cf->global->router_id;
|
||||||
struct ospf_area *oa;
|
struct ospf_area *oa;
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
|
|
||||||
|
OSPF_TRACE(D_EVENTS, "Flushing AS-external-LSA for %I/%d",
|
||||||
|
n->n.prefix, n->n.pxlen);
|
||||||
|
|
||||||
/* FIXME proper handling of LSA IDs and check for the same network */
|
/* FIXME proper handling of LSA IDs and check for the same network */
|
||||||
u32 lsaid = ipa_to_lsaid(n->n.prefix);
|
u32 lsaid = ipa_to_lsaid(n->n.prefix);
|
||||||
|
|
||||||
|
@ -987,7 +985,7 @@ originate_link_lsa(struct ospf_iface *ifa)
|
||||||
void *body;
|
void *body;
|
||||||
|
|
||||||
/* FIXME check for vlink and skip that? */
|
/* FIXME check for vlink and skip that? */
|
||||||
OSPF_TRACE(D_EVENTS, "Originating Link_lsa for iface %s.", ifa->iface->name);
|
OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->iface->name);
|
||||||
|
|
||||||
lsa.age = 0;
|
lsa.age = 0;
|
||||||
lsa.type = LSA_T_LINK;
|
lsa.type = LSA_T_LINK;
|
||||||
|
@ -1000,6 +998,10 @@ originate_link_lsa(struct ospf_iface *ifa)
|
||||||
lsasum_calculate(&lsa, body);
|
lsasum_calculate(&lsa, body);
|
||||||
ifa->link_lsa = lsa_install_new(po, &lsa, dom, body);
|
ifa->link_lsa = lsa_install_new(po, &lsa, dom, body);
|
||||||
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
|
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
|
||||||
|
|
||||||
|
/* Just to be sure to not forget on our link LSA */
|
||||||
|
if (ifa->state == OSPF_IS_DR)
|
||||||
|
schedule_net_lsa(ifa);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1050,6 +1052,7 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) ||
|
if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) ||
|
||||||
(a->flags & IA_SECONDARY) ||
|
(a->flags & IA_SECONDARY) ||
|
||||||
(a->flags & IA_UNNUMBERED) ||
|
(a->flags & IA_UNNUMBERED) ||
|
||||||
|
(a->scope <= SCOPE_LINK) ||
|
||||||
configured_stubnet(oa, a))
|
configured_stubnet(oa, a))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1081,14 +1084,17 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
void
|
void
|
||||||
originate_prefix_rt_lsa(struct ospf_area *oa)
|
originate_prefix_rt_lsa(struct ospf_area *oa)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header lsa;
|
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
|
struct proto *p = &po->proto;
|
||||||
u32 rid = po->proto.cf->global->router_id;
|
u32 rid = po->proto.cf->global->router_id;
|
||||||
|
struct ospf_lsa_header lsa;
|
||||||
void *body;
|
void *body;
|
||||||
|
|
||||||
|
OSPF_TRACE(D_EVENTS, "Originating router prefix-LSA for area %R", oa->areaid);
|
||||||
|
|
||||||
lsa.age = 0;
|
lsa.age = 0;
|
||||||
lsa.type = LSA_T_PREFIX;
|
lsa.type = LSA_T_PREFIX;
|
||||||
lsa.id = 1 << 31;
|
lsa.id = 0;
|
||||||
lsa.rt = rid;
|
lsa.rt = rid;
|
||||||
lsa.sn = oa->pxr_lsa ? (oa->pxr_lsa->lsa.sn + 1) : LSA_INITSEQNO;
|
lsa.sn = oa->pxr_lsa ? (oa->pxr_lsa->lsa.sn + 1) : LSA_INITSEQNO;
|
||||||
u32 dom = oa->areaid;
|
u32 dom = oa->areaid;
|
||||||
|
@ -1128,12 +1134,14 @@ prefix_same(u32 *b1, u32 *b2)
|
||||||
static inline u32 *
|
static inline u32 *
|
||||||
prefix_advance(u32 *buf)
|
prefix_advance(u32 *buf)
|
||||||
{
|
{
|
||||||
return buf + prefix_space(buf);
|
int pxl = *buf >> 24;
|
||||||
|
return buf + IPV6_PREFIX_WORDS(pxl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_prefix(struct proto_ospf *po, u32 *px, u32 *pxl, int *pxc)
|
add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
|
||||||
{
|
{
|
||||||
|
u32 *pxl = lsab_offset(po, offset);
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < *pxc; i++)
|
for (i = 0; i < *pxc; i++)
|
||||||
{
|
{
|
||||||
|
@ -1154,19 +1162,31 @@ add_prefix(struct proto_ospf *po, u32 *px, u32 *pxl, int *pxc)
|
||||||
(*pxc)++;
|
(*pxc)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_link_lsa(struct proto_ospf *po, struct top_hash_entry *en, int offset, int *pxc)
|
||||||
|
{
|
||||||
|
struct ospf_lsa_link *ll = en->lsa_body;
|
||||||
|
u32 *pxb = ll->rest;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < ll->pxcount; j++)
|
||||||
|
{
|
||||||
|
add_prefix(po, pxb, offset, pxc);
|
||||||
|
pxb = prefix_advance(pxb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
|
originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
|
||||||
{
|
{
|
||||||
struct proto_ospf *po = ifa->oa->po;
|
struct proto_ospf *po = ifa->oa->po;
|
||||||
struct ospf_lsa_prefix *lp;
|
struct ospf_lsa_prefix *lp;
|
||||||
struct ospf_lsa_link *ll;
|
|
||||||
struct ospf_neighbor *n;
|
struct ospf_neighbor *n;
|
||||||
struct top_hash_entry *en;
|
struct top_hash_entry *en;
|
||||||
u32 rid = po->proto.cf->global->router_id;
|
u32 rid = po->proto.cf->global->router_id;
|
||||||
u32 *pxb;
|
int pxc, offset;
|
||||||
int i, j, offset;
|
|
||||||
|
|
||||||
|
|
||||||
ASSERT(po->lsab_used == 0);
|
ASSERT(po->lsab_used == 0);
|
||||||
lp = lsab_allocz(po, sizeof(struct ospf_lsa_prefix));
|
lp = lsab_allocz(po, sizeof(struct ospf_lsa_prefix));
|
||||||
|
@ -1175,26 +1195,20 @@ originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
|
||||||
lp->ref_rt = rid;
|
lp->ref_rt = rid;
|
||||||
lp = NULL; /* buffer might be reallocated later */
|
lp = NULL; /* buffer might be reallocated later */
|
||||||
|
|
||||||
i = 0;
|
pxc = 0;
|
||||||
offset = po->lsab_used;
|
offset = po->lsab_used;
|
||||||
|
|
||||||
/* Find all Link LSA associated with the link and merge their prefixes */
|
/* Find all Link LSAs associated with the link and merge their prefixes */
|
||||||
|
if (ifa->link_lsa)
|
||||||
|
add_link_lsa(po, ifa->link_lsa, offset, &pxc);
|
||||||
|
|
||||||
WALK_LIST(n, ifa->neigh_list)
|
WALK_LIST(n, ifa->neigh_list)
|
||||||
if ((n->state == NEIGHBOR_FULL) &&
|
if ((n->state == NEIGHBOR_FULL) &&
|
||||||
(en = ospf_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK)))
|
(en = ospf_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK)))
|
||||||
{
|
add_link_lsa(po, en, offset, &pxc);
|
||||||
ll = en->lsa_body;
|
|
||||||
pxb = ll->rest;
|
|
||||||
|
|
||||||
for (j = 0; j < ll->pxcount; j++)
|
|
||||||
{
|
|
||||||
add_prefix(po, pxb, lsab_offset(po, offset), &i);
|
|
||||||
pxb = prefix_advance(pxb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lp = po->lsab;
|
lp = po->lsab;
|
||||||
lp->pxcount = i;
|
lp->pxcount = pxc;
|
||||||
*length = po->lsab_used + sizeof(struct ospf_lsa_header);
|
*length = po->lsab_used + sizeof(struct ospf_lsa_header);
|
||||||
return lsab_flush(po);
|
return lsab_flush(po);
|
||||||
}
|
}
|
||||||
|
@ -1202,11 +1216,15 @@ originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
|
||||||
void
|
void
|
||||||
originate_prefix_net_lsa(struct ospf_iface *ifa)
|
originate_prefix_net_lsa(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header lsa;
|
|
||||||
struct proto_ospf *po = ifa->oa->po;
|
struct proto_ospf *po = ifa->oa->po;
|
||||||
|
struct proto *p = &po->proto;
|
||||||
u32 rid = po->proto.cf->global->router_id;
|
u32 rid = po->proto.cf->global->router_id;
|
||||||
|
struct ospf_lsa_header lsa;
|
||||||
void *body;
|
void *body;
|
||||||
|
|
||||||
|
OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s",
|
||||||
|
ifa->iface->name);
|
||||||
|
|
||||||
lsa.age = 0;
|
lsa.age = 0;
|
||||||
lsa.type = LSA_T_PREFIX;
|
lsa.type = LSA_T_PREFIX;
|
||||||
lsa.id = ifa->iface->index;
|
lsa.id = ifa->iface->index;
|
||||||
|
@ -1231,8 +1249,9 @@ flush_prefix_net_lsa(struct ospf_iface *ifa)
|
||||||
if (en == NULL)
|
if (en == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSPF_TRACE(D_EVENTS, "Flushing Net Prefix lsa for iface \"%s\".",
|
OSPF_TRACE(D_EVENTS, "Flushing network prefix-LSA for iface %s",
|
||||||
ifa->iface->name);
|
ifa->iface->name);
|
||||||
|
|
||||||
en->lsa.sn += 1;
|
en->lsa.sn += 1;
|
||||||
en->lsa.age = LSA_MAXAGE;
|
en->lsa.age = LSA_MAXAGE;
|
||||||
lsasum_calculate(&en->lsa, en->lsa_body);
|
lsasum_calculate(&en->lsa, en->lsa_body);
|
||||||
|
@ -1283,7 +1302,7 @@ ospf_top_hash_u32(u32 a)
|
||||||
static inline unsigned
|
static inline unsigned
|
||||||
ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type)
|
ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type)
|
||||||
{
|
{
|
||||||
/* In OSPFv2, we don't know Router ID when looking for network lsas.
|
/* In OSPFv2, we don't know Router ID when looking for network LSAs.
|
||||||
dirty patch to make rt table calculation work. */
|
dirty patch to make rt table calculation work. */
|
||||||
|
|
||||||
return (ospf_top_hash_u32(lsaid) + type +
|
return (ospf_top_hash_u32(lsaid) + type +
|
||||||
|
|
|
@ -472,6 +472,9 @@ krt_capable(rte *e)
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
case RTD_ROUTER:
|
case RTD_ROUTER:
|
||||||
|
if (ipa_has_link_scope(a->gw) && (a->iface == NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
case RTD_DEVICE:
|
case RTD_DEVICE:
|
||||||
case RTD_BLACKHOLE:
|
case RTD_BLACKHOLE:
|
||||||
case RTD_UNREACHABLE:
|
case RTD_UNREACHABLE:
|
||||||
|
@ -514,6 +517,11 @@ nl_send_route(struct krt_proto *p, rte *e, int new)
|
||||||
case RTD_ROUTER:
|
case RTD_ROUTER:
|
||||||
r.r.rtm_type = RTN_UNICAST;
|
r.r.rtm_type = RTN_UNICAST;
|
||||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
|
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
|
||||||
|
|
||||||
|
/* a->iface != NULL checked in krt_capable() */
|
||||||
|
if (ipa_has_link_scope(a->gw))
|
||||||
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case RTD_DEVICE:
|
case RTD_DEVICE:
|
||||||
if (!a->iface)
|
if (!a->iface)
|
||||||
|
|
Loading…
Reference in a new issue