📄 ospf_opaque.c
字号:
* Opaque-LSA control information per opaque-type. * Single Opaque-Type may have multiple instances; each of them will be * identified by their opaque-id. */struct opaque_info_per_type{ u_char lsa_type; u_char opaque_type; enum { PROC_NORMAL, PROC_SUSPEND } status; /* * Thread for (re-)origination scheduling for this opaque-type. * * Initial origination of Opaque-LSAs is controlled by generic * Opaque-LSA handling module so that same opaque-type entries are * called all at once when certain conditions are met. * However, there might be cases that some Opaque-LSA clients need * to (re-)originate their own Opaque-LSAs out-of-sync with others. * This thread is prepared for that specific purpose. */ struct thread *t_opaque_lsa_self; /* * Backpointer to an "owner" which is LSA-type dependent. * type-9: struct ospf_interface * type-10: struct ospf_area * type-11: struct ospf */ void *owner; /* Collection of callback functions for this opaque-type. */ struct ospf_opaque_functab *functab; /* List of Opaque-LSA control informations per opaque-id. */ list id_list;};/* Opaque-LSA control information per opaque-id. */struct opaque_info_per_id{ u_int32_t opaque_id; /* Thread for refresh/flush scheduling for this opaque-type/id. */ struct thread *t_opaque_lsa_self; /* Backpointer to Opaque-LSA control information per opaque-type. */ struct opaque_info_per_type *opqctl_type; /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */ struct ospf_lsa *lsa;};static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new){ struct ospf *top; struct opaque_info_per_type *oipt; if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE, sizeof (struct opaque_info_per_type))) == NULL) { zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno)); goto out; } switch (new->data->type) { case OSPF_OPAQUE_LINK_LSA: oipt->owner = new->oi; listnode_add (new->oi->opaque_lsa_self, oipt); break; case OSPF_OPAQUE_AREA_LSA: oipt->owner = new->area; listnode_add (new->area->opaque_lsa_self, oipt); break; case OSPF_OPAQUE_AS_LSA: top = ospf_lookup (); if (new->area != NULL && (top = new->area->ospf) == NULL) { free_opaque_info_per_type ((void *) oipt); oipt = NULL; goto out; /* This case may not exist. */ } oipt->owner = top; listnode_add (top->opaque_lsa_self, oipt); break; default: zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type); free_opaque_info_per_type ((void *) oipt); oipt = NULL; goto out; /* This case may not exist. */ } oipt->lsa_type = new->data->type; oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr)); oipt->status = PROC_NORMAL; oipt->t_opaque_lsa_self = NULL; oipt->functab = functab; functab->oipt = oipt; oipt->id_list = list_new (); oipt->id_list->del = free_opaque_info_per_id;out: return oipt;}static voidfree_opaque_info_per_type (void *val){ struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val; struct opaque_info_per_id *oipi; struct ospf_lsa *lsa; listnode node; /* Control information per opaque-id may still exist. */ for (node = listhead (oipt->id_list); node; nextnode (node)) { if ((oipi = getdata (node)) == NULL) continue; if ((lsa = oipi->lsa) == NULL) continue; if (IS_LSA_MAXAGE (lsa)) continue; ospf_opaque_lsa_flush_schedule (lsa); } /* Remove "oipt" from its owner's self-originated LSA list. */ switch (oipt->lsa_type) { case OSPF_OPAQUE_LINK_LSA: { struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner); listnode_delete (oi->opaque_lsa_self, oipt); break; } case OSPF_OPAQUE_AREA_LSA: { struct ospf_area *area = (struct ospf_area *)(oipt->owner); listnode_delete (area->opaque_lsa_self, oipt); break; } case OSPF_OPAQUE_AS_LSA: { struct ospf *top = (struct ospf *)(oipt->owner); listnode_delete (top->opaque_lsa_self, oipt); break; } default: zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type); break; /* This case may not exist. */ } OSPF_TIMER_OFF (oipt->t_opaque_lsa_self); list_delete (oipt->id_list); XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt); return;}static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa){ struct ospf *top; struct ospf_area *area; struct ospf_interface *oi; list listtop = NULL; listnode node; struct opaque_info_per_type *oipt = NULL; u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)); switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: if ((oi = lsa->oi) != NULL) listtop = oi->opaque_lsa_self; else zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?"); break; case OSPF_OPAQUE_AREA_LSA: if ((area = lsa->area) != NULL) listtop = area->opaque_lsa_self; else zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?"); break; case OSPF_OPAQUE_AS_LSA: top = ospf_lookup (); if ((area = lsa->area) != NULL && (top = area->ospf) == NULL) { zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?"); break; /* Unlikely to happen. */ } listtop = top->opaque_lsa_self; break; default: zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type); break; } if (listtop != NULL) for (node = listhead (listtop); node; nextnode (node)) if ((oipt = getdata (node)) != NULL) if (oipt->opaque_type == key) return oipt; return NULL;}static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new){ struct opaque_info_per_id *oipi; if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID, sizeof (struct opaque_info_per_id))) == NULL) { zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno)); goto out; } oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr)); oipi->t_opaque_lsa_self = NULL; oipi->opqctl_type = oipt; oipi->lsa = ospf_lsa_lock (new); listnode_add (oipt->id_list, oipi);out: return oipi;}static voidfree_opaque_info_per_id (void *val){ struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val; OSPF_TIMER_OFF (oipi->t_opaque_lsa_self); if (oipi->lsa != NULL) ospf_lsa_unlock (oipi->lsa); XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi); return;}static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa){ listnode node; struct opaque_info_per_id *oipi; u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)); for (node = listhead (oipt->id_list); node; nextnode (node)) if ((oipi = getdata (node)) != NULL) if (oipi->opaque_id == key) return oipi; return NULL;}static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new){ struct ospf_opaque_functab *functab; struct opaque_info_per_type *oipt; struct opaque_info_per_id *oipi = NULL; if ((functab = ospf_opaque_functab_lookup (new)) == NULL) goto out; if ((oipt = lookup_opaque_info_by_type (new)) == NULL && (oipt = register_opaque_info_per_type (functab, new)) == NULL) goto out; if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL) goto out;out: return oipi;}/*------------------------------------------------------------------------* * Followings are (vty) configuration functions for Opaque-LSAs handling. *------------------------------------------------------------------------*/DEFUN (capability_opaque, capability_opaque_cmd, "capability opaque", "Enable specific OSPF feature\n" "Opaque LSA\n"){ struct ospf *ospf = (struct ospf *) vty->index; /* Turn on the "master switch" of opaque-lsa capability. */ if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("Opaque capability: OFF -> ON"); SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE); ospf_renegotiate_optional_capabilities (ospf); } return CMD_SUCCESS;}ALIAS (capability_opaque, ospf_opaque_capable_cmd, "ospf opaque-lsa", "OSPF specific commands\n" "Enable the Opaque-LSA capability (rfc2370)\n");DEFUN (no_capability_opaque, no_capability_opaque_cmd, "no capability opaque", NO_STR "Enable specific OSPF feature\n" "Opaque LSA\n"){ struct ospf *ospf = (struct ospf *) vty->index; /* Turn off the "master switch" of opaque-lsa capability. */ if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("Opaque capability: ON -> OFF"); UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE); ospf_renegotiate_optional_capabilities (ospf); } return CMD_SUCCESS;}ALIAS (no_capability_opaque, no_ospf_opaque_capable_cmd, "no ospf opaque-lsa", NO_STR "OSPF specific commands\n" "Disable the Opaque-LSA capability (rfc2370)\n");static voidospf_opaque_register_vty (void){ install_element (OSPF_NODE, &capability_opaque_cmd); install_element (OSPF_NODE, &no_capability_opaque_cmd); install_element (OSPF_NODE, &ospf_opaque_capable_cmd); install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd); return;}/*------------------------------------------------------------------------* * Followings are collection of user-registered function callers. *------------------------------------------------------------------------*/static intopaque_lsa_new_if_callback (list funclist, struct interface *ifp){ listnode node; struct ospf_opaque_functab *functab; int rc = -1; for (node = listhead (funclist); node; nextnode (node)) if ((functab = getdata (node)) != NULL) if (functab->new_if_hook != NULL) if ((* functab->new_if_hook)(ifp) != 0) goto out; rc = 0;out: return rc;}static intopaque_lsa_del_if_callback (list funclist, struct interface *ifp){ listnode node; struct ospf_opaque_functab *functab; int rc = -1; for (node = listhead (funclist); node; nextnode (node)) if ((functab = getdata (node)) != NULL) if (functab->del_if_hook != NULL) if ((* functab->del_if_hook)(ifp) != 0) goto out; rc = 0;out: return rc;}static voidopaque_lsa_ism_change_callback (list funclist, struct ospf_interface *oi, int old_status){ listnode node; struct ospf_opaque_functab *functab; for (node = listhead (funclist); node; nextnode (node)) if ((functab = getdata (node)) != NULL) if (functab->ism_change_hook != NULL) (* functab->ism_change_hook)(oi, old_status); return;}static voidopaque_lsa_nsm_change_callback (list funclist, struct ospf_neighbor *nbr, int old_status){ listnode node; struct ospf_opaque_functab *functab; for (node = listhead (funclist); node; nextnode (node)) if ((functab = getdata (node)) != NULL) if (functab->nsm_change_hook != NULL) (* functab->nsm_change_hook)(nbr, old_status); return;}static voidopaque_lsa_config_write_router_callback (list funclist, struct vty *vty){ listnode node; struct ospf_opaque_functab *functab; for (node = listhead (funclist); node; nextnode (node)) if ((functab = getdata (node)) != NULL) if (functab->config_write_router != NULL) (* functab->config_write_router)(vty); return;}static voidopaque_lsa_config_write_if_callback (list funclist, struct vty *vty, struct interface *ifp){ listnode node; struct ospf_opaque_functab *functab; for (node = listhead (funclist); node; nextnode (node)) if ((functab = getdata (node)) != NULL) if (functab->config_write_if != NULL) (* functab->config_write_if)(vty, ifp); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -