#include "ospf6_spf.h"
#include "ospf6d.h"
#include "ospf6_bfd.h"
+#include "ospf6_zebra.h"
DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names")
DEFINE_QOBJ_TYPE(ospf6_interface)
struct ospf6_interface *oi;
unsigned int iobuflen;
- oi = (struct ospf6_interface *)XCALLOC(MTYPE_OSPF6_IF,
- sizeof(struct ospf6_interface));
+ oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
oi->area = (struct ospf6_area *)NULL;
oi->neighbor_list = list_new();
THREAD_OFF(oi->thread_send_hello);
THREAD_OFF(oi->thread_send_lsupdate);
THREAD_OFF(oi->thread_send_lsack);
+ THREAD_OFF(oi->thread_sso);
ospf6_lsdb_remove_all(oi->lsdb);
ospf6_lsdb_remove_all(oi->lsupdate_list);
ospf6_bfd_info_free(&(oi->bfd_info));
+ /* disable from area list if possible */
+ ospf6_area_interface_delete(oi);
+
XFREE(MTYPE_OSPF6_IF, oi);
}
THREAD_OFF(oi->thread_send_hello);
THREAD_OFF(oi->thread_send_lsupdate);
THREAD_OFF(oi->thread_send_lsack);
+ THREAD_OFF(oi->thread_sso);
THREAD_OFF(oi->thread_network_lsa);
THREAD_OFF(oi->thread_link_lsa);
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
return;
- if (oi->area == NULL)
- return;
if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
return;
if (if_is_operative(ifp)
&& (ospf6_interface_get_linklocal_address(oi->interface)
|| if_is_loopback(oi->interface)))
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_up, oi, 0);
else
- thread_add_event(master, interface_down, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
return;
}
oi = (struct ospf6_interface *)THREAD_ARG(thread);
assert(oi && oi->interface);
+ if (!oi->type_cfg)
+ oi->type = ospf6_default_iftype(oi->interface);
+
+ /*
+ * Remove old pointer. If this thread wasn't a timer this
+ * operation won't make a difference, because it is already NULL.
+ */
+ oi->thread_sso = NULL;
+
if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug("Interface Event %s: [InterfaceUp]",
oi->interface->name);
return 0;
}
+#ifdef __FreeBSD__
+ /*
+ * XXX: Schedule IPv6 group join for later, otherwise we might
+ * lose the multicast group registration caused by IPv6 group
+ * leave race.
+ */
+ if (oi->sso_try_cnt == 0) {
+ oi->sso_try_cnt++;
+ zlog_info("Scheduling %s for sso", oi->interface->name);
+ thread_add_timer(master, interface_up, oi,
+ OSPF6_INTERFACE_SSO_RETRY_INT,
+ &oi->thread_sso);
+ return 0;
+ }
+#endif /* __FreeBSD__ */
+
/* Join AllSPFRouters */
if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP)
< 0) {
"Scheduling %s for sso retry, trial count: %d",
oi->interface->name, oi->sso_try_cnt);
thread_add_timer(master, interface_up, oi,
- OSPF6_INTERFACE_SSO_RETRY_INT, NULL);
+ OSPF6_INTERFACE_SSO_RETRY_INT,
+ &oi->thread_sso);
}
return 0;
}
}
/* decide next interface state */
- if ((if_is_pointopoint(oi->interface))
- || (oi->type == OSPF_IFTYPE_POINTOPOINT)) {
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
} else if (oi->priority == 0)
ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
/* Stop Hellos */
THREAD_OFF(oi->thread_send_hello);
+ /* Stop trying to set socket options. */
+ THREAD_OFF(oi->thread_sso);
+
/* Leave AllSPFRouters */
if (oi->state > OSPF6_INTERFACE_DOWN)
ospf6_sso(oi->interface->ifindex, &allspfrouters6,
}
+static const char *ospf6_iftype_str(uint8_t iftype)
+{
+ switch (iftype) {
+ case OSPF_IFTYPE_LOOPBACK:
+ return "LOOPBACK";
+ case OSPF_IFTYPE_BROADCAST:
+ return "BROADCAST";
+ case OSPF_IFTYPE_POINTOPOINT:
+ return "POINTOPOINT";
+ }
+ return "UNKNOWN";
+}
+
/* show specified interface structure */
static int ospf6_interface_show(struct vty *vty, struct interface *ifp)
{
struct prefix *p;
struct listnode *i;
char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32];
- const char *type;
+ uint8_t default_iftype;
struct timeval res, now;
char duration[32];
struct ospf6_lsa *lsa;
- /* check physical interface type */
- if (if_is_loopback(ifp))
- type = "LOOPBACK";
- else if (if_is_broadcast(ifp))
- type = "BROADCAST";
- else if (if_is_pointopoint(ifp))
- type = "POINTOPOINT";
- else
- type = "UNKNOWN";
+ default_iftype = ospf6_default_iftype(ifp);
vty_out(vty, "%s is %s, type %s\n", ifp->name,
- (if_is_operative(ifp) ? "up" : "down"), type);
+ (if_is_operative(ifp) ? "up" : "down"),
+ ospf6_iftype_str(default_iftype));
vty_out(vty, " Interface ID: %d\n", ifp->ifindex);
if (ifp->info == NULL) {
} else
oi = (struct ospf6_interface *)ifp->info;
+ if (if_is_operative(ifp) && oi->type != default_iftype)
+ vty_out(vty, " Operating as type %s\n",
+ ospf6_iftype_str(oi->type));
+
vty_out(vty, " Internet Address:\n");
for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
THREAD_OFF(oi->thread_send_hello);
+ THREAD_OFF(oi->thread_sso);
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
THREAD_OFF(on->inactivity_timer);
UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
THREAD_OFF(oi->thread_send_hello);
- oi->thread_send_hello = NULL;
+ THREAD_OFF(oi->thread_sso);
thread_add_event(master, ospf6_hello_send, oi, 0,
&oi->thread_send_hello);
}
assert(oi);
+ oi->type_cfg = true;
+
if (strncmp(argv[idx_network]->arg, "b", 1) == 0) {
if (oi->type == OSPF_IFTYPE_BROADCAST)
return CMD_SUCCESS;
}
/* Reset the interface */
- thread_add_event(master, interface_down, oi, 0, NULL);
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
+ thread_execute(master, interface_up, oi, 0);
return CMD_SUCCESS;
}
return CMD_SUCCESS;
}
+ oi->type_cfg = false;
+
type = ospf6_default_iftype(ifp);
if (oi->type == type) {
return CMD_SUCCESS;
oi->type = type;
/* Reset the interface */
- thread_add_event(master, interface_down, oi, 0, NULL);
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
+ thread_execute(master, interface_up, oi, 0);
return CMD_SUCCESS;
}
if (oi->mtu_ignore)
vty_out(vty, " ipv6 ospf6 mtu-ignore\n");
- if (oi->type != ospf6_default_iftype(ifp)) {
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
- vty_out(vty,
- " ipv6 ospf6 network point-to-point\n");
- else if (oi->type == OSPF_IFTYPE_BROADCAST)
- vty_out(vty, " ipv6 ospf6 network broadcast\n");
- }
+ if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
+ vty_out(vty, " ipv6 ospf6 network point-to-point\n");
+ else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST)
+ vty_out(vty, " ipv6 ospf6 network broadcast\n");
ospf6_bfd_write_config(vty, oi);
INTERFACE_NODE, "%s(config-if)# ", 1 /* VTYSH */
};
+static int ospf6_ifp_create(struct interface *ifp)
+{
+ if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+ zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name,
+ ifp->ifindex, ifp->mtu6);
+ ospf6_interface_if_add(ifp);
+
+ return 0;
+}
+
+static int ospf6_ifp_up(struct interface *ifp)
+{
+ if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+ zlog_debug(
+ "Zebra Interface state change: "
+ "%s index %d flags %llx metric %d mtu %d bandwidth %d",
+ ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu6, ifp->bandwidth);
+
+ ospf6_interface_state_update(ifp);
+
+ return 0;
+}
+
+static int ospf6_ifp_down(struct interface *ifp)
+{
+ if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+ zlog_debug(
+ "Zebra Interface state change: "
+ "%s index %d flags %llx metric %d mtu %d bandwidth %d",
+ ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu6, ifp->bandwidth);
+
+ ospf6_interface_state_update(ifp);
+
+ return 0;
+}
+
+static int ospf6_ifp_destroy(struct interface *ifp)
+{
+ if (if_is_up(ifp))
+ zlog_warn("Zebra: got delete of %s, but interface is still up",
+ ifp->name);
+
+ if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+ zlog_debug("Zebra Interface delete: %s index %d mtu %d",
+ ifp->name, ifp->ifindex, ifp->mtu6);
+
+ return 0;
+}
+
void ospf6_interface_init(void)
{
/* Install interface node. */
install_node(&interface_node, config_write_ospf6_interface);
if_cmd_init();
+ if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up,
+ ospf6_ifp_down, ospf6_ifp_destroy);
install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
zlog_debug("Interface %s: clear by reset", ifp->name);
/* Reset the interface */
- thread_add_event(master, interface_down, oi, 0, NULL);
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
+ thread_execute(master, interface_up, oi, 0);
}
/* Clear interface */