DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n",
p->name, ifa->iface->name, ifa->addr->ip);
- /* Now we should send a hello packet */
pkt = ospf_tx_buffer(ifa);
- op = &pkt->ospf_packet;
-
- /* Now fill ospf_hello header */
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
-#ifdef OSPFv2
- pkt->netmask = ipa_mkmask(ifa->addr->pxlen);
- ipa_hton(pkt->netmask);
- if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
- pkt->netmask = IPA_NONE;
-#endif
-
- pkt->helloint = ntohs(ifa->helloint);
- pkt->priority = ifa->priority;
-
-#ifdef OSPFv3
- pkt->iface_id = htonl(ifa->iface_id);
-
- pkt->options3 = ifa->oa->options >> 16;
- pkt->options2 = ifa->oa->options >> 8;
-#endif
- pkt->options = ifa->oa->options;
-
-#ifdef OSPFv2
- pkt->deadint = htonl(ifa->deadint);
- pkt->dr = htonl(ipa_to_u32(ifa->drip));
- pkt->bdr = htonl(ipa_to_u32(ifa->bdrip));
-#else /* OSPFv3 */
- pkt->deadint = htons(ifa->deadint);
- pkt->dr = htonl(ifa->drid);
- pkt->bdr = htonl(ifa->bdrid);
-#endif
+ if (ospf_is_v2(po))
+ {
+ struct ospf_hello2_packet *ps = (void *) pkt;
+
+ ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen));
+
+ if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
+ ps->netmask = 0;
+
+ ps->helloint = ntohs(ifa->helloint);
+ ps->options = ifa->oa->options;
+ ps->priority = ifa->priority;
+ ps->deadint = htonl(ifa->deadint);
+ ps->dr = htonl(ipa_to_u32(ifa->drip));
+ ps->bdr = htonl(ipa_to_u32(ifa->bdrip));
+
+ length = sizeof(struct ospf_hello2_packet);
+ neighbors = ps->neighbors;
+ }
+ else
+ {
+ struct ospf_hello3_packet *ps = (void *) pkt;
+
- ps->iface_id = htonl(ifa->iface->index);
++ ps->iface_id = htonl(ifa->iface_id);
+ ps->priority = ifa->priority;
+ ps->options3 = ifa->oa->options >> 16;
+ ps->options2 = ifa->oa->options >> 8;
+ ps->options = ifa->oa->options;
+ ps->helloint = ntohs(ifa->helloint);
+ ps->deadint = htons(ifa->deadint);
+ ps->dr = htonl(ifa->drid);
+ ps->bdr = htonl(ifa->bdrid);
+
+ length = sizeof(struct ospf_hello3_packet);
+ neighbors = ps->neighbors;
+ }
- /* Fill all neighbors */
i = 0;
+ max = (ospf_pkt_bufsize(ifa) - length) / sizeof(u32);
+ /* Fill all neighbors */
if (kind != OHS_SHUTDOWN)
{
- u32 *pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet));
WALK_LIST(neigh, ifa->neigh_list)
{
- if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_bufsize(ifa))
+ if (i == max)
{
log(L_WARN "%s: Too many neighbors on interface %s", p->name, ifa->iface->name);
break;
if (ifa->type != old_type)
log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
- p->name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
+ po->proto.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
+ /* Assign iface ID, for vlinks, this is ugly hack */
+ ifa->iface_id = (ifa->type != OSPF_IT_VLINK) ? iface->index : oa->po->last_vlink_id++;
init_list(&ifa->neigh_list);
init_list(&ifa->nbma_list);
}
#endif /* little endian */
- {
+
+
+int
+lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa)
-
++{
++ /* Handle inactive vlinks */
++ if (ifa->state == OSPF_IS_DOWN)
++ return 0;
++
+ /* 4.5.2 (Case 2) */
- return ifa->iface->index == domain;
+ switch (LSA_SCOPE(type))
+ {
+ case LSA_SCOPE_LINK:
- *domain = ifa->iface->index;
++ return ifa->iface_id == domain;
+
+ case LSA_SCOPE_AREA:
+ return ifa->oa->areaid == domain;
+
+ case LSA_SCOPE_AS:
+ if (ifa->type == OSPF_IT_VLINK)
+ return 0;
+ if (!oa_is_ext(ifa->oa))
+ return 0;
+ return 1;
+
+ default:
+ log(L_ERR "OSPF: LSA with invalid scope");
+ return 0;
+ }
+}
+
+
+static int
+unknown_lsa_type(u32 type)
+{
+ switch (type)
+ {
+ case LSA_T_RT:
+ case LSA_T_NET:
+ case LSA_T_SUM_NET:
+ case LSA_T_SUM_RT:
+ case LSA_T_EXT:
+ case LSA_T_NSSA:
+ case LSA_T_LINK:
+ case LSA_T_PREFIX:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+#define LSA_V2_TMAX 8
+static const u16 lsa_v2_types[LSA_V2_TMAX] =
+ {0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA};
+
+void
+lsa_xxxxtype(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain)
+{
+ if (ospf_is_v2(ifa->oa->po))
+ {
+ itype = itype & LSA_T_V2_MASK;
+ itype = (itype < LSA_V2_TMAX) ? lsa_v2_types[itype] : 0;
+ }
+ else
+ {
+ /* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */
+ if (unknown_lsa_type(itype) && !(itype & LSA_UBIT))
+ itype = itype & ~LSA_SCOPE_MASK;
+ }
+
+ *otype = itype;
+
+ switch (LSA_SCOPE(itype))
+ {
+ case LSA_SCOPE_LINK:
++ *domain = ifa->iface_id;
+ return;
+
+ case LSA_SCOPE_AREA:
+ *domain = ifa->oa->areaid;
+ return;
+
+ case LSA_SCOPE_AS:
+ default:
+ *domain = 0;
+ return;
+ }
+}
+
+
+
/*
void
buf_dump(const char *hdr, const byte *buf, int blen)
}
}
-
-#ifdef OSPFv2
-
-int
-ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
-{
- if (lsa->type == LSA_T_EXT)
- {
- if (ifa->type == OSPF_IT_VLINK)
- return 0;
- if (!oa_is_ext(ifa->oa))
- return 0;
- return 1;
- }
- else
- return ifa->oa->areaid == domain;
-}
-
-#else /* OSPFv3 */
-
-static int
-unknown_lsa_type(struct ospf_lsa_header *lsa)
-{
- switch (lsa->type)
- {
- case LSA_T_RT:
- case LSA_T_NET:
- case LSA_T_SUM_NET:
- case LSA_T_SUM_RT:
- case LSA_T_EXT:
- case LSA_T_NSSA:
- case LSA_T_LINK:
- case LSA_T_PREFIX:
- return 0;
-
- default:
- return 1;
- }
-}
-
-int
-ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
-{
- u32 scope = LSA_SCOPE(lsa);
-
- /* Handle inactive vlinks */
- if (ifa->state == OSPF_IS_DOWN)
- return 0;
-
- /* 4.5.2 (Case 2) */
- if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT))
- scope = LSA_SCOPE_LINK;
-
- switch (scope)
- {
- case LSA_SCOPE_LINK:
- return ifa->iface_id == domain;
-
- case LSA_SCOPE_AREA:
- return ifa->oa->areaid == domain;
-
- case LSA_SCOPE_AS:
- if (ifa->type == OSPF_IT_VLINK)
- return 0;
- if (!oa_is_ext(ifa->oa))
- return 0;
- return 1;
-
- default:
- log(L_ERR "LSA with invalid scope");
- return 0;
- }
-}
-
-#endif
--
/**
* ospf_lsupd_flood - send received or generated lsa to the neighbors
* @po: OSPF protocol
me.priority = ifa->priority;
me.ip = ifa->addr->ip;
-#ifdef OSPFv2
- me.dr = ipa_to_u32(ifa->drip);
- me.bdr = ipa_to_u32(ifa->bdrip);
-#else /* OSPFv3 */
- me.dr = ifa->drid;
- me.bdr = ifa->bdrid;
+ me.dr = ospf_is_v2(po) ? ipa_to_u32(ifa->drip) : ifa->drid;
+ me.bdr = ospf_is_v2(po) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
- me.iface_id = ifa->iface->index;
+ me.iface_id = ifa->iface_id;
-#endif
add_tail(&ifa->neigh_list, NODE & me);
static int
lsa_compare_for_state(const void *p1, const void *p2)
{
- struct top_hash_entry * he1 = * (struct top_hash_entry **) p1;
- struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
+ struct top_hash_entry *he1 = * (struct top_hash_entry **) p1;
+ struct top_hash_entry *he2 = * (struct top_hash_entry **) p2;
struct ospf_lsa_header *lsa1 = &(he1->lsa);
struct ospf_lsa_header *lsa2 = &(he2->lsa);
+ struct ospf_lsa_header lsatmp1, lsatmp2;
+ u16 lsa1_type = he1->lsa_type;
+ u16 lsa2_type = he2->lsa_type;
- if (he1->domain != he2->domain)
- return he1->domain - he2->domain;
+ if (he1->domain < he2->domain)
+ return -1;
+ if (he1->domain > he2->domain)
+ return 1;
-#ifdef OSPFv3
- struct ospf_lsa_header lsatmp1, lsatmp2;
- int px1 = (lsa1->type == LSA_T_PREFIX);
- int px2 = (lsa2->type == LSA_T_PREFIX);
+ /* px1 or px2 assumes OSPFv3 */
+ int px1 = (lsa1_type == LSA_T_PREFIX);
+ int px2 = (lsa2_type == LSA_T_PREFIX);
if (px1)
+ {
lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
+ lsa1_type = lsa1->type_raw; /* FIXME: handle unknown ref_type */
+ }
if (px2)
+ {
lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
-#endif
+ lsa2_type = lsa2->type_raw;
+ }
- int nt1 = (lsa1->type == LSA_T_NET);
- int nt2 = (lsa2->type == LSA_T_NET);
+
+ int nt1 = (lsa1_type == LSA_T_NET);
+ int nt2 = (lsa2_type == LSA_T_NET);
if (nt1 != nt2)
return nt1 - nt2;
if (nt1)
{
-#ifdef OSPFv3
- /* In OSPFv3, neworks are named base on ID of DR */
- if (lsa1->rt < lsa2->rt)
- return -1;
- if (lsa1->rt > lsa2->rt)
- return 1;
-#endif
+ /* In OSPFv3, networks are named based on ID of DR */
- if (lsa_compare_ospf3 && (lsa1->rt != lsa2->rt))
- return lsa1->rt - lsa2->rt;
++ if (lsa_compare_ospf3)
++ {
++ if (lsa1->rt < lsa2->rt)
++ return -1;
++ if (lsa1->rt > lsa2->rt)
++ return 1;
++ }
/* For OSPFv2, this is IP of the network,
for OSPFv3, this is interface ID */
- if (lsa1->id != lsa2->id)
- return lsa1->id - lsa2->id;
+ if (lsa1->id < lsa2->id)
+ return -1;
+ if (lsa1->id > lsa2->id)
+ return 1;
-#ifdef OSPFv3
if (px1 != px2)
return px1 - px2;
-#endif
return lsa1->sn - lsa2->sn;
}
else
{
- if (lsa1->rt != lsa2->rt)
- return lsa1->rt - lsa2->rt;
+ if (lsa1->rt < lsa2->rt)
+ return -1;
+ if (lsa1->rt > lsa2->rt)
+ return 1;
- if (lsa1_type != lsa2_type)
- return lsa1_type - lsa2_type;
-
- if (lsa1->id != lsa2->id)
- return lsa1->id - lsa2->id;
- if (lsa1->type < lsa2->type)
++ if (lsa1_type < lsa2_type)
+ return -1;
- if (lsa1->type > lsa2->type)
++ if (lsa1_type > lsa2_type)
+ return 1;
+
+ if (lsa1->id < lsa2->id)
+ return -1;
+ if (lsa1->id > lsa2->id)
+ return 1;
-#ifdef OSPFv3
if (px1 != px2)
return px1 - px2;
-#endif
return lsa1->sn - lsa2->sn;
}
WALK_LIST(neigh, ifa->neigh_list)
if (neigh->state == NEIGHBOR_FULL)
{
- u32 data = (ifa->addr->flags & IA_PEER) ? ifa->iface->index : ipa_to_u32(ifa->addr->ip);
- ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- ln->type = LSART_PTP;
- ln->id = neigh->rid;
- ln->data = (ifa->addr->flags & IA_PEER) ?
- ifa->iface_id : ipa_to_u32(ifa->addr->ip);
- ln->metric = ifa->cost;
- ln->padding = 0;
++ u32 data = (ifa->addr->flags & IA_PEER) ? ifa->iface_id : ipa_to_u32(ifa->addr->ip);
+ add_rt2_lsa_link(po, LSART_PTP, neigh->rid, data, ifa->cost);
i++;
}
break;
{
if (n->state == NEIGHBOR_FULL)
{
-#ifdef OSPFv3
+ /* In OSPFv3, we would like to merge options from Link LSAs of added neighbors */
- 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_id, n->iface_id, n->rid, LSA_T_LINK);
if (en)
options |= ((struct ospf_lsa_link *) en->lsa_body)->options;
-#endif
net->routers[i] = n->rid;
i++;
ifa->iface->name);
lsa.age = 0;
- lsa.type = LSA_T_NET;
-
-#ifdef OSPFv2
- lsa.options = ifa->oa->options;
- lsa.id = ipa_to_u32(ifa->addr->ip);
-#else /* OSPFv3 */
- lsa.id = ifa->iface_id;
-#endif
-
+ lsa.type_raw = LSA_T_NET;
- lsa.id = ospf_is_v2(po) ? ipa_to_u32(ifa->addr->ip) : ifa->iface->index;
++ lsa.id = ospf_is_v2(po) ? ipa_to_u32(ifa->addr->ip) : ifa->iface_id;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(ifa->net_lsa);
+ lsa_fix_options(po, &lsa, ifa->oa->options);
- body = originate_net_lsa_body(ifa, &lsa.length, po);
+ body = originate_net_lsa_body(po, ifa, &lsa.length);
lsasum_calculate(&lsa, body);
ifa->net_lsa = lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
void
originate_link_lsa(struct ospf_iface *ifa)
{
- struct ospf_lsa_header lsa;
struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
+ struct ospf_lsa_header lsa;
- u32 dom = ifa->iface->index;
++ u32 dom = ifa->iface_id;
void *body;
/* FIXME check for vlink and skip that? */
OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->iface->name);
lsa.age = 0;
- lsa.type = LSA_T_LINK;
+ lsa.type_raw = LSA_T_LINK;
- lsa.id = ifa->iface->index;
+ lsa.id = ifa->iface_id;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(ifa->link_lsa);
- u32 dom = ifa->iface_id;
body = originate_link_lsa_body(ifa, &lsa.length);
lsasum_calculate(&lsa, body);
ifa->iface->name);
lsa.age = 0;
- lsa.type = LSA_T_PREFIX;
+ lsa.type_raw = LSA_T_PREFIX;
- lsa.id = ifa->iface->index;
+ lsa.id = ifa->iface_id;
lsa.rt = po->router_id;
lsa.sn = get_seqnum(ifa->pxn_lsa);
- u32 dom = ifa->oa->areaid;
body = originate_prefix_net_lsa_body(ifa, &lsa.length);
lsasum_calculate(&lsa, body);