summaryrefslogtreecommitdiff
path: root/zebra/interface.c
diff options
context:
space:
mode:
authorpaul <paul>2006-01-25 04:31:40 +0000
committerpaul <paul>2006-01-25 04:31:40 +0000
commit5c78b3d006e6926f938796cffa08e8e14fb8e7af (patch)
tree19f8f80511cba84e0d70ac22667321a4a7df0d60 /zebra/interface.c
parent590188b67db4021b9d1552238ef49482dd5f0123 (diff)
[zebra/solaris] Interface state fixups for Solaris.
2006-01-25 Paul Jakma <paul.jakma@sun.com> * (general) More solaris PF_ROUTE hacks. The IFF_UP mangling for solaris was incomplete on the PF_ROUTE side. fix it. This changeset generally uglifies things. For some future work I'd like to see the state changes seperated out from the details of the code. Differences between systems might then be slightly easier to implement without convoluted hacks. Changes should be specific to Solaris mostly, however also tested on FreeBSD 6. * if_ioctl_solaris.c: (interface_list_ioctl) ignore ~IFF_UP interfaces, we'll hear about them when/if interface goes up through NEWADDR. Update flags explicitely at end of it to kick mangling. * ioctl_solaris.c: (if_mangle_up) removed to interface.c, in kind. (lifreq_set_name) more convenient to take the string, than the ifp. (if_get_flags_direct) new convenience function, returns the actual flags. Used during bootstrap in if_ioctl_solaris.c to peek at flags of logical interfaces to see whether or not to ignore them. (if_get_flags) ENXIO means it's gone, poke out IFF_UP and kick flags update. (if_{un,}set_flags) flags argument should be 64bit. * ioctl.{c,h}: flags argument should be 64bit. * interface.h: Add a 'primary_state' flag to struct zebra_if on SUNOS_5. Export if_flags_update. * interface.c: (if_flags_mangle) moved over in kind from ioctl_solaris.c. Nasty kludge to try get IFF_UP right, as much as is possible. Also keep track of the actual IFF_UP value for the primary interface, so we can know when the ifp must be deleted. (if_flags_update) Take a new interface flags value, apply it to the interface, and take whatever actions are required due to flag transitions. (if_refresh) flag state change logic is moved out to previous. Just call if_get_flags, which will end up using previous to effect the update of flags. (if_flag_dump_vty) IFF_IPV{4,6} aren't interesting, VIRTUAL and NOXMIT are though. * kernel_socket.c: (ifm_read) Down->Down transitions shouldn't create ifp, for non-IFANNOUNCE systems. Use if_flags_update to update flags. flag transition logic is now handled automatically through if_flags_update. (ifam_read) Better to call if_refresh *after* adding connected addresses, as connected count affects IFF_UP on IFF_UP-mangled systems. On Solaris, Up->Down due to DELADDR means we need to delete the ifp - the IFINFO might already have been and gone. * rt.h: include other dependent headers.
Diffstat (limited to 'zebra/interface.c')
-rw-r--r--zebra/interface.c86
1 files changed, 71 insertions, 15 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 5f9c7a23..d4266f59 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -187,6 +187,73 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc)
return 0;
}
+/* if_flags_mangle: A place for hacks that require mangling
+ * or tweaking the interface flags.
+ *
+ * ******************** Solaris flags hacks **************************
+ *
+ * Solaris IFF_UP flag reflects only the primary interface as the
+ * routing socket only sends IFINFO for the primary interface. Hence
+ * ~IFF_UP does not per se imply all the logical interfaces are also
+ * down - which we only know of as addresses. Instead we must determine
+ * whether the interface really is up or not according to how many
+ * addresses are still attached. (Solaris always sends RTM_DELADDR if
+ * an interface, logical or not, goes ~IFF_UP).
+ *
+ * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
+ * are addresses left in struct connected, not just the actual underlying
+ * IFF_UP flag.
+ *
+ * We must hence remember the real state of IFF_UP, which we do in
+ * struct zebra_if.primary_state.
+ *
+ * Setting IFF_UP within zebra to administratively shutdown the
+ * interface will affect only the primary interface/address on Solaris.
+ ************************End Solaris flags hacks ***********************
+ */
+static inline void
+if_flags_mangle (struct interface *ifp, uint64_t *newflags)
+{
+#ifdef SUNOS_5
+ struct zebra_if *zif = ifp->info;
+
+ zif->primary_state = *newflags & (IFF_UP & 0xff);
+
+ if (CHECK_FLAG (zif->primary_state, IFF_UP)
+ || listcount(ifp->connected) > 0)
+ SET_FLAG (*newflags, IFF_UP);
+ else
+ UNSET_FLAG (*newflags, IFF_UP);
+#endif /* SUNOS_5 */
+}
+
+/* Update the flags field of the ifp with the new flag set provided.
+ * Take whatever actions are required for any changes in flags we care
+ * about.
+ *
+ * newflags should be the raw value, as obtained from the OS.
+ */
+void
+if_flags_update (struct interface *ifp, uint64_t newflags)
+{
+ if_flags_mangle (ifp, &newflags);
+
+ if (if_is_operative (ifp))
+ {
+ /* operative -> inoperative? */
+ ifp->flags = newflags;
+ if (!if_is_operative (ifp))
+ if_down (ifp);
+ }
+ else
+ {
+ /* inoperative -> operative? */
+ ifp->flags = newflags;
+ if (if_is_operative (ifp))
+ if_up (ifp);
+ }
+}
+
/* Wake up configured address if it is not in current kernel
address. */
static void
@@ -478,23 +545,12 @@ if_down (struct interface *ifp)
void
if_refresh (struct interface *ifp)
{
- if (if_is_operative (ifp))
- {
- if_get_flags (ifp);
- if (! if_is_operative (ifp))
- if_down (ifp);
- }
- else
- {
- if_get_flags (ifp);
- if (if_is_operative (ifp))
- if_up (ifp);
- }
+ if_get_flags (ifp);
}
/* Printout flag information into vty */
static void
-if_flag_dump_vty (struct vty *vty, unsigned long flag)
+if_flag_dump_vty (struct vty *vty, uint64_t flag)
{
int separator = 0;
@@ -526,8 +582,8 @@ if_flag_dump_vty (struct vty *vty, unsigned long flag)
IFF_OUT_VTY (IFF_LINK2, "LINK2");
IFF_OUT_VTY (IFF_MULTICAST, "MULTICAST");
#ifdef SOLARIS_IPV6
- IFF_OUT_VTY (IFF_IPV4, "IFF_IPv4");
- IFF_OUT_VTY (IFF_IPV6, "IFF_IPv6");
+ IFF_OUT_VTY (IFF_VIRTUAL, "IFF_VIRTUAL");
+ IFF_OUT_VTY (IFF_NOXMIT, "IFF_NOXMIT");
#endif /* SOLARIS_IPV6 */
vty_out (vty, ">");
}