📄 ospf_opaque.c
字号:
return &lsa;}static intospf_opaque_type9_lsa_reoriginate_timer (struct thread *t){ struct opaque_info_per_type *oipt; struct ospf_opaque_functab *functab; struct ospf *top; struct ospf_interface *oi; int rc = -1; oipt = THREAD_ARG (t); oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?"); goto out; } oi = (struct ospf_interface *) oipt->owner; if ((top = oi_to_top (oi)) == NULL) { zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?"); goto out; } if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE) || ! ospf_if_is_enable (oi) || ospf_nbr_count_opaque_capable (oi) == 0) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type); oipt->status = PROC_SUSPEND; rc = 0; goto out; } if (IS_DEBUG_OSPF_EVENT) zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi)); rc = (* functab->lsa_originator)(oi);out: return rc;}static intospf_opaque_type10_lsa_reoriginate_timer (struct thread *t){ struct opaque_info_per_type *oipt; struct ospf_opaque_functab *functab; listnode node; struct ospf *top; struct ospf_area *area; struct ospf_interface *oi; int n, rc = -1; oipt = THREAD_ARG (t); oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?"); goto out; } area = (struct ospf_area *) oipt->owner; if (area == NULL || (top = area->ospf) == NULL) { zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?"); goto out; } /* There must be at least one "opaque-capable, full-state" neighbor. */ n = 0; for (node = listhead (area->oiflist); node; nextnode (node)) { if ((oi = getdata (node)) == NULL) continue; if ((n = ospf_nbr_count_opaque_capable (oi)) > 0) break; } if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type); oipt->status = PROC_SUSPEND; rc = 0; goto out; } if (IS_DEBUG_OSPF_EVENT) zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa (area->area_id)); rc = (* functab->lsa_originator)(area);out: return rc;}static intospf_opaque_type11_lsa_reoriginate_timer (struct thread *t){ struct opaque_info_per_type *oipt; struct ospf_opaque_functab *functab; struct ospf *top; int rc = -1; oipt = THREAD_ARG (t); oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?"); goto out; } if ((top = (struct ospf *) oipt->owner) == NULL) { zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?"); goto out; } if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type); oipt->status = PROC_SUSPEND; rc = 0; goto out; } if (IS_DEBUG_OSPF_EVENT) zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type); rc = (* functab->lsa_originator)(top);out: return rc;}extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */voidospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0){ struct ospf *ospf = ospf; struct opaque_info_per_type *oipt; struct opaque_info_per_id *oipi; struct ospf_lsa *lsa; int delay; ospf = ospf_lookup (); if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL) { zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?"); goto out; } /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */ if ((lsa = oipi->lsa) == NULL) { zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?"); goto out; } if (oipi->t_opaque_lsa_self != NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); goto out; } /* Delete this lsa from neighbor retransmit-list. */ switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa); break; case OSPF_OPAQUE_AS_LSA: ospf_ls_retransmit_delete_nbr_as (ospf, lsa); break; default: zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type); goto out; } delay = ospf_lsa_refresh_delay (lsa); if (IS_DEBUG_OSPF_EVENT) zlog_info ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self, ospf_opaque_lsa_refresh_timer, oipi, delay);out: return;}static intospf_opaque_lsa_refresh_timer (struct thread *t){ struct opaque_info_per_id *oipi; struct ospf_opaque_functab *functab; struct ospf_lsa *lsa; if (IS_DEBUG_OSPF_EVENT) zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)"); oipi = THREAD_ARG (t); oipi->t_opaque_lsa_self = NULL; if ((lsa = oipi->lsa) != NULL) if ((functab = oipi->opqctl_type->functab) != NULL) if (functab->lsa_refresher != NULL) (* functab->lsa_refresher)(lsa); return 0;}voidospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0){ struct ospf *ospf = ospf; struct opaque_info_per_type *oipt; struct opaque_info_per_id *oipi; struct ospf_lsa *lsa; ospf = ospf_lookup (); if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL) { zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?"); goto out; } /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */ if ((lsa = oipi->lsa) == NULL) { zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?"); goto out; } /* Delete this lsa from neighbor retransmit-list. */ switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa); break; case OSPF_OPAQUE_AS_LSA: ospf_ls_retransmit_delete_nbr_as (ospf, lsa); break; default: zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type); goto out; } /* Dequeue listnode entry from the list. */ listnode_delete (oipt->id_list, oipi); /* Avoid misjudgement in the next lookup. */ if (listcount (oipt->id_list) == 0) oipt->id_list->head = oipt->id_list->tail = NULL; /* Disassociate internal control information with the given lsa. */ oipi->lsa = NULL; free_opaque_info_per_id ((void *) oipi); /* Force given lsa's age to MaxAge. */ lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); if (IS_DEBUG_OSPF_EVENT) zlog_info ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); /* This lsa will be flushed and removed eventually. */ ospf_lsa_maxage (ospf, lsa);out: return;}/*------------------------------------------------------------------------* * Followings are control functions to block origination after restart. *------------------------------------------------------------------------*/static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);voidospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas){ struct ospf *top; struct ospf_area *area; struct ospf_interface *oi; listnode node1, node2; struct ospf_lsa *lsa; if ((top = oi_to_top (nbr->oi)) == NULL) goto out; /* * If an instance of self-originated Opaque-LSA is found in the given * LSA list, and it is not installed to LSDB yet, exclude it from the * list "nbr->ls_req". In this way, it is assured that an LSReq message, * which might be sent in the process of flooding, will not request for * the LSA to be flushed immediately; otherwise, depending on timing, * an LSUpd message will carry instances of target LSAs with MaxAge, * while other LSUpd message might carry old LSA instances (non-MaxAge). * Obviously, the latter would trigger miserable situations that repeat * installation and removal of unwanted LSAs indefinitely. */ for (node1 = listhead (lsas); node1; nextnode (node1)) { if ((lsa = getdata (node1)) == NULL) continue; /* Filter out unwanted LSAs. */ if (! IS_OPAQUE_LSA (lsa->data->type)) continue; if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id)) continue; /* * Don't touch an LSA which has MaxAge; two possible cases. * * 1) This LSA has originally flushed by myself (received LSUpd * message's router-id is equal to my router-id), and flooded * back by an opaque-capable router. * * 2) This LSA has expired in an opaque-capable router and thus * flushed by the router. */ if (IS_LSA_MAXAGE (lsa)) continue; /* If the LSA has installed in the LSDB, nothing to do here. */ if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL) continue; /* Ok, here we go. */ switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: oi = nbr->oi; ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa); break; case OSPF_OPAQUE_AREA_LSA: area = nbr->oi->area; for (node2 = listhead (area->oiflist); node2; nextnode (node2)) { if ((oi = getdata (node2)) == NULL) continue; ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa); } break; case OSPF_OPAQUE_AS_LSA: for (node2 = listhead (top->oiflist); node2; nextnode (node2)) { if ((oi = getdata (node2)) == NULL) continue; ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa); } break; default: break; } }out: return;}static voidospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa){ struct route_node *rn; struct ospf_neighbor *onbr; struct ospf_lsa *ls_req; for (rn = route_top (nbrs); rn; rn = route_next (rn)) { if ((onbr = rn->info) == NULL) continue; if (onbr == inbr) continue; if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL) continue; if (IS_DEBUG_OSPF_EVENT) zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa)); ospf_ls_request_delete (onbr, ls_req);/* ospf_check_nbr_loading (onbr);*//* XXX */ } return;}voidospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas){ struct ospf *top; listnode node, next; struct ospf_lsa *lsa; u_char before; if ((top = oi_to_top (nbr->oi)) == NULL) goto out; before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque); for (node = listhead (lsas); node; node = next) { next = node->next; if ((lsa = getdata (node)) == NULL) continue; listnode_delete (lsas, lsa); /* * Since these LSA entries are not yet installed into corresponding * LSDB, just flush them without calling ospf_ls_maxage() afterward. */ lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT); ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa); break; case OSPF_OPAQU
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -