summaryrefslogtreecommitdiffstats
path: root/zebra/interface.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2020-04-17 01:39:14 +0200
committerGitHub <noreply@github.com>2020-04-17 01:39:14 +0200
commita83014ccd66477fa624ee54eb97e0a2a30a5a106 (patch)
tree3d7faaad38c74b74409785cc54c0a58b8f72a23a /zebra/interface.c
parentMerge pull request #6135 from opensourcerouting/cli-node-cleanup (diff)
parentlib: suppress formatting on yang.c module array (diff)
downloadfrr-a83014ccd66477fa624ee54eb97e0a2a30a5a106.tar.xz
frr-a83014ccd66477fa624ee54eb97e0a2a30a5a106.zip
Merge pull request #6247 from FRRouting/nb_conversions
Merge nb_converions branch to master
Diffstat (limited to 'zebra/interface.c')
-rw-r--r--zebra/interface.c302
1 files changed, 284 insertions, 18 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index cad382ff0..586a59bb1 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -500,7 +500,7 @@ void if_flags_update(struct interface *ifp, uint64_t newflags)
/* Wake up configured address if it is not in current kernel
address. */
-static void if_addr_wakeup(struct interface *ifp)
+void if_addr_wakeup(struct interface *ifp)
{
struct listnode *node, *nnode;
struct connected *ifc;
@@ -1888,6 +1888,24 @@ DEFUN (show_interface_desc_vrf_all,
return CMD_SUCCESS;
}
+int if_multicast_set(struct interface *ifp)
+{
+ struct zebra_if *if_data;
+
+ if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
+ if (if_set_flags(ifp, IFF_MULTICAST) < 0) {
+ zlog_debug("Can't set multicast flag on interface %s",
+ ifp->name);
+ return -1;
+ }
+ if_refresh(ifp);
+ }
+ if_data = ifp->info;
+ if_data->multicast = IF_ZEBRA_MULTICAST_ON;
+
+ return 0;
+}
+
DEFUN (multicast,
multicast_cmd,
"multicast",
@@ -1911,6 +1929,24 @@ DEFUN (multicast,
return CMD_SUCCESS;
}
+int if_multicast_unset(struct interface *ifp)
+{
+ struct zebra_if *if_data;
+
+ if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
+ if (if_unset_flags(ifp, IFF_MULTICAST) < 0) {
+ zlog_debug("Can't unset multicast flag on interface %s",
+ ifp->name);
+ return -1;
+ }
+ if_refresh(ifp);
+ }
+ if_data = ifp->info;
+ if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
+
+ return 0;
+}
+
DEFUN (no_multicast,
no_multicast_cmd,
"no multicast",
@@ -1935,23 +1971,35 @@ DEFUN (no_multicast,
return CMD_SUCCESS;
}
-DEFUN (linkdetect,
- linkdetect_cmd,
- "link-detect",
- "Enable link detection on interface\n")
+int if_linkdetect(struct interface *ifp, bool detect)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
int if_was_operative;
if_was_operative = if_is_no_ptm_operative(ifp);
- SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
+ if (detect) {
+ SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
- /* When linkdetection is enabled, if might come down */
- if (!if_is_no_ptm_operative(ifp) && if_was_operative)
- if_down(ifp);
+ /* When linkdetection is enabled, if might come down */
+ if (!if_is_no_ptm_operative(ifp) && if_was_operative)
+ if_down(ifp);
+ } else {
+ UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
+ /* Interface may come up after disabling link detection */
+ if (if_is_operative(ifp) && !if_was_operative)
+ if_up(ifp);
+ }
/* FIXME: Will defer status change forwarding if interface
does not come down! */
+ return 0;
+}
+
+DEFUN(linkdetect, linkdetect_cmd, "link-detect",
+ "Enable link detection on interface\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+
+ if_linkdetect(ifp, true);
return CMD_SUCCESS;
}
@@ -1964,18 +2012,29 @@ DEFUN (no_linkdetect,
"Disable link detection on interface\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
- int if_was_operative;
- if_was_operative = if_is_no_ptm_operative(ifp);
- UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
+ if_linkdetect(ifp, false);
+
+ return CMD_SUCCESS;
+}
- /* Interface may come up after disabling link detection */
- if (if_is_operative(ifp) && !if_was_operative)
- if_up(ifp);
+int if_shutdown(struct interface *ifp)
+{
+ struct zebra_if *if_data;
- /* FIXME: see linkdetect_cmd */
+ if (ifp->ifindex != IFINDEX_INTERNAL) {
+ /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
+ rtadv_stop_ra(ifp);
+ if (if_unset_flags(ifp, IFF_UP) < 0) {
+ zlog_debug("Can't shutdown interface %s", ifp->name);
+ return -1;
+ }
+ if_refresh(ifp);
+ }
+ if_data = ifp->info;
+ if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
- return CMD_SUCCESS;
+ return 0;
}
DEFUN (shutdown_if,
@@ -2003,6 +2062,30 @@ DEFUN (shutdown_if,
return CMD_SUCCESS;
}
+int if_no_shutdown(struct interface *ifp)
+{
+ struct zebra_if *if_data;
+
+ if (ifp->ifindex != IFINDEX_INTERNAL) {
+ if (if_set_flags(ifp, IFF_UP | IFF_RUNNING) < 0) {
+ zlog_debug("Can't up interface %s", ifp->name);
+ return -1;
+ }
+ if_refresh(ifp);
+
+ /* Some addresses (in particular, IPv6 addresses on Linux) get
+ * removed when the interface goes down. They need to be
+ * readded.
+ */
+ if_addr_wakeup(ifp);
+ }
+
+ if_data = ifp->info;
+ if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
+
+ return 0;
+}
+
DEFUN (no_shutdown_if,
no_shutdown_if_cmd,
"no shutdown",
@@ -2758,6 +2841,79 @@ DEFUN (no_link_params_use_bw,
return CMD_SUCCESS;
}
+int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
+ const char *label, struct prefix *pp)
+{
+ struct zebra_if *if_data;
+ struct prefix_ipv4 lp;
+ struct prefix_ipv4 *p;
+ struct connected *ifc;
+ enum zebra_dplane_result dplane_res;
+
+ if_data = ifp->info;
+
+ lp.family = prefix->family;
+ lp.prefix = prefix->u.prefix4;
+ lp.prefixlen = prefix->prefixlen;
+ apply_mask_ipv4(&lp);
+
+ ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL);
+ if (!ifc) {
+ ifc = connected_new();
+ ifc->ifp = ifp;
+
+ /* Address. */
+ p = prefix_ipv4_new();
+ *p = lp;
+ ifc->address = (struct prefix *)p;
+
+ if (pp) {
+ SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
+ p = prefix_ipv4_new();
+ *p = *(struct prefix_ipv4 *)pp;
+ ifc->destination = (struct prefix *)p;
+ }
+
+ /* Label. */
+ if (label)
+ ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
+
+ /* Add to linked list. */
+ listnode_add(ifp->connected, ifc);
+ }
+
+ /* This address is configured from zebra. */
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
+ SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
+
+ /* In case of this route need to install kernel. */
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
+ && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
+ && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
+ /* Some system need to up the interface to set IP address. */
+ if (!if_is_up(ifp)) {
+ if_set_flags(ifp, IFF_UP | IFF_RUNNING);
+ if_refresh(ifp);
+ }
+
+ dplane_res = dplane_intf_addr_set(ifp, ifc);
+ if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
+ zlog_debug(
+ "dplane can't set interface IP address: %s.\n",
+ dplane_res2str(dplane_res));
+ return NB_ERR;
+ }
+
+ SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
+ /* The address will be advertised to zebra clients when the
+ * notification
+ * from the kernel has been received.
+ * It will also be added to the subnet chain list, then. */
+ }
+
+ return 0;
+}
+
static int ip_address_install(struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
const char *label)
@@ -2852,6 +3008,51 @@ static int ip_address_install(struct vty *vty, struct interface *ifp,
return CMD_SUCCESS;
}
+int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix)
+{
+ struct connected *ifc = NULL;
+ enum zebra_dplane_result dplane_res;
+
+ if (prefix->family == AF_INET) {
+ /* Check current interface address. */
+ ifc = connected_check_ptp(ifp, prefix, NULL);
+ if (!ifc) {
+ zlog_debug("interface %s Can't find address\n",
+ ifp->name);
+ return -1;
+ }
+
+ } else if (prefix->family == AF_INET6) {
+ /* Check current interface address. */
+ ifc = connected_check(ifp, prefix);
+ }
+
+ if (!ifc) {
+ zlog_debug("interface %s Can't find address\n", ifp->name);
+ return -1;
+ }
+ UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
+
+ /* This is not real address or interface is not active. */
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
+ || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
+ listnode_delete(ifp->connected, ifc);
+ connected_free(&ifc);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* This is real route. */
+ dplane_res = dplane_intf_addr_unset(ifp, ifc);
+ if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
+ zlog_debug("Can't unset interface IP address: %s.\n",
+ dplane_res2str(dplane_res));
+ return -1;
+ }
+ UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
+
+ return 0;
+}
+
static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
const char *label)
@@ -3005,6 +3206,71 @@ DEFUN (no_ip_address_label,
}
#endif /* HAVE_NETLINK */
+int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
+ const char *label)
+{
+ struct zebra_if *if_data;
+ struct prefix_ipv6 cp;
+ struct connected *ifc;
+ struct prefix_ipv6 *p;
+ enum zebra_dplane_result dplane_res;
+
+ if_data = ifp->info;
+
+ cp.family = prefix->family;
+ cp.prefixlen = prefix->prefixlen;
+ cp.prefix = prefix->u.prefix6;
+ apply_mask_ipv6(&cp);
+
+ ifc = connected_check(ifp, (struct prefix *)&cp);
+ if (!ifc) {
+ ifc = connected_new();
+ ifc->ifp = ifp;
+
+ /* Address. */
+ p = prefix_ipv6_new();
+ *p = cp;
+ ifc->address = (struct prefix *)p;
+
+ /* Label. */
+ if (label)
+ ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
+
+ /* Add to linked list. */
+ listnode_add(ifp->connected, ifc);
+ }
+
+ /* This address is configured from zebra. */
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
+ SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
+
+ /* In case of this route need to install kernel. */
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
+ && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
+ && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
+ /* Some system need to up the interface to set IP address. */
+ if (!if_is_up(ifp)) {
+ if_set_flags(ifp, IFF_UP | IFF_RUNNING);
+ if_refresh(ifp);
+ }
+
+ dplane_res = dplane_intf_addr_set(ifp, ifc);
+ if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
+ zlog_debug(
+ "dplane can't set interface IP address: %s.\n",
+ dplane_res2str(dplane_res));
+ return NB_ERR;
+ }
+
+ SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
+ /* The address will be advertised to zebra clients when the
+ * notification
+ * from the kernel has been received. */
+ }
+
+ return 0;
+}
+
static int ipv6_address_install(struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
const char *label)