[Xorp-hackers] [PATCH] FIB upcall/event support, please review

Bruce M Simpson bms@spc.org
Fri, 5 Nov 2004 14:08:52 -0800


--WfZ7S8PLGjBY9Voh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

[Cc: to possibly interested parties]

Here is the next piece of forwarding table notification support. Because
this messes with the innards of XORP on FreeBSD, I could do with some
review and additional testing before this goes in.

This is needed in order to support ad-hoc/on-demand routing protocols. It's
currently targeted only at BSD, but could easily be adapted to Linux.

The last part missing is the wiring-up of these upcall notifications to
the XrlFtiTransactionManager, by way of the FibTableObserver and
FtiConfigTableObserver::propagate_fib_changes(); that will come next.

Then, routing protocols implemented as XORP processes will be able to
receive route resolve/miss upcalls, if they implement the XRL interface
'fea_fib_client' and ask for them.

Regards,
BMS

--WfZ7S8PLGjBY9Voh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fea-rtm-upcalls1.diff"

In the routing socket implementation of the Fti subsystem,
change the parse_buffer_rtm() method in classes
FtiConfigEntryGet and FtiConfigTableGet to accept an enum,
RtmParseType, which the caller uses to convey which subset
of BSD routing socket messages it is interested in. Tidy
up the methods afterwards.

Update callers to use the new function signature. Because 
the methods compile to stubs, don't wrap the enum 
declaration with #ifdef HAVE_ROUTING_SOCKETS. IfConfigGet 
never needs to see this, so don't touch it.

Index: fticonfig.hh
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig.hh,v
retrieving revision 1.23
diff -u -p -r1.23 fticonfig.hh
--- fticonfig.hh	5 Nov 2004 00:47:43 -0000	1.23
+++ fticonfig.hh	5 Nov 2004 22:02:20 -0000
@@ -25,6 +25,15 @@
 #include "libxorp/trie.hh"
 
 #include "fte.hh"
+
+// Knobs for parse_buffer_rtm() in routing socket FtiConfig implementation
+// to denote what caller is interested in.
+enum FtiRtmParseType {
+   CHANGES,		// RTM_ADD, RTM_CHANGE, RTM_DELETE, RTM_GET.
+   GET,			// RTM_GET only.
+   UPCALLS		// RTM_MISS and RTM_RESOLVE.
+};
+
 #include "fticonfig_entry_get.hh"
 #include "fticonfig_entry_set.hh"
 #include "fticonfig_entry_observer.hh"
Index: fticonfig_entry_get.hh
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig_entry_get.hh,v
retrieving revision 1.17
diff -u -p -r1.17 fticonfig_entry_get.hh
--- fticonfig_entry_get.hh	26 Oct 2004 23:58:29 -0000	1.17
+++ fticonfig_entry_get.hh	5 Nov 2004 22:02:20 -0000
@@ -110,12 +110,12 @@ public:
      * @param fte the Fte storage to store the parsed information.
      * @param buf the buffer with the data to parse.
      * @param buf_bytes buf_bytes the size of the data in the buffer.
-     * @param is_rtm_get_only if true, consider only the RTM_GET entries.
+     * @param type the subset of RTM messages that caller is interested in.
      * @return true on success, otherwise false.
      * @see FteX.
      */
     bool parse_buffer_rtm(FteX& fte, const uint8_t *buf, size_t buf_bytes,
-			  bool is_rtm_get_only);
+			  FtiRtmParseType type);
 
     /**
      * Parse information about routing entry information received from
Index: fticonfig_entry_get_rtsock.cc
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig_entry_get_rtsock.cc,v
retrieving revision 1.21
diff -u -p -r1.21 fticonfig_entry_get_rtsock.cc
--- fticonfig_entry_get_rtsock.cc	26 Oct 2004 23:55:16 -0000	1.21
+++ fticonfig_entry_get_rtsock.cc	5 Nov 2004 22:02:20 -0000
@@ -303,7 +303,7 @@ FtiConfigEntryGetRtsock::lookup_route_by
 	return (false);
     }
     if (parse_buffer_rtm(fte, _rs_reader.buffer(), _rs_reader.buffer_size(),
-			 true)
+			 FtiRtmParseType(GET))
 	!= true) {
 	return (false);
     }
@@ -446,7 +446,7 @@ FtiConfigEntryGetRtsock::lookup_route_by
 	return (false);
     }
     if (parse_buffer_rtm(fte, _rs_reader.buffer(), _rs_reader.buffer_size(),
-			 true)
+			 FtiRtmParseType(GET))
 	!= true) {
 	return (false);
     }
Index: fticonfig_entry_parse_rtm.cc
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig_entry_parse_rtm.cc,v
retrieving revision 1.7
diff -u -p -r1.7 fticonfig_entry_parse_rtm.cc
--- fticonfig_entry_parse_rtm.cc	5 Nov 2004 01:27:53 -0000	1.7
+++ fticonfig_entry_parse_rtm.cc	5 Nov 2004 22:02:20 -0000
@@ -39,7 +39,8 @@
 
 #ifndef HAVE_ROUTING_SOCKETS
 bool
-FtiConfigEntryGet::parse_buffer_rtm(FteX& , const uint8_t* , size_t , bool )
+FtiConfigEntryGet::parse_buffer_rtm(FteX& , const uint8_t* , size_t ,
+				    FtiRtmParseType)
 {
     return false;
 }
@@ -48,13 +49,14 @@ FtiConfigEntryGet::parse_buffer_rtm(FteX
 
 bool
 FtiConfigEntryGet::parse_buffer_rtm(FteX& fte, const uint8_t* buf,
-				    size_t buf_bytes, bool is_rtm_get_only)
+				    size_t buf_bytes, FtiRtmParseType type)
 {
-    const struct rt_msghdr* rtm = reinterpret_cast<const struct rt_msghdr*>(buf);
+    const struct rt_msghdr* rtm =
+	reinterpret_cast<const struct rt_msghdr*>(buf);
     const uint8_t* last = buf + buf_bytes;
-    
+
     for (const uint8_t* ptr = buf; ptr < last; ptr += rtm->rtm_msglen) {
-    	rtm = reinterpret_cast<const struct rt_msghdr*>(ptr);
+	rtm = reinterpret_cast<const struct rt_msghdr*>(ptr);
 	if (RTM_VERSION != rtm->rtm_version) {
 	    XLOG_ERROR("RTM version mismatch: expected %d got %d",
 		       RTM_VERSION,
@@ -62,30 +64,35 @@ FtiConfigEntryGet::parse_buffer_rtm(FteX
 	    continue;
 	}
 
-	if (is_rtm_get_only) {
-	    //
-	    // Consider only the RTM_GET entries.
-	    //
-	    if (rtm->rtm_type != RTM_GET)
+	// XXX: ignore entries with an error
+	if (rtm->rtm_errno != 0)
+	    continue;
+
+	if (type == FtiRtmParseType(GET)) {
+	    if ((rtm->rtm_type != RTM_GET) || !(rtm->rtm_flags & RTF_UP))
+		continue;
+	} else if (type == FtiRtmParseType(UPCALLS)) {
+	    // Upcalls may not be supported in some implementations.
+#ifdef RTM_MISS
+	    if (rtm->rtm_type != RTM_MISS)
+		continue;
+#endif
+#ifdef RTM_RESOLVE
+	    if (rtm->rtm_type != RTM_RESOLVE)
 		continue;
-	    if (! (rtm->rtm_flags & RTF_UP))
+#endif
+	} else if (type == FtiRtmParseType(CHANGES)) {
+	    if ((rtm->rtm_type != RTM_ADD) && (rtm->rtm_type != RTM_DELETE) &&
+		(rtm->rtm_type != RTM_CHANGE) && (rtm->rtm_type != RTM_GET))
 		continue;
+	} else {
+		return (false);
 	}
 
-	if ((rtm->rtm_type != RTM_ADD)
-	    && (rtm->rtm_type != RTM_DELETE)
-	    && (rtm->rtm_type != RTM_CHANGE)
-	    && (rtm->rtm_type != RTM_GET)) {
-	    continue;
-        }
-
-	if (rtm->rtm_errno != 0)
-	    continue;		// XXX: ignore entries with an error
-	
 	return (RtmUtils::rtm_get_to_fte_cfg(fte, ftic().iftree(), rtm));
     }
-    
-    return false;
+
+    return (false);
 }
 
 #endif // HAVE_ROUTING_SOCKETS
Index: fticonfig_table_get.hh
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig_table_get.hh,v
retrieving revision 1.14
diff -u -p -r1.14 fticonfig_table_get.hh
--- fticonfig_table_get.hh	26 Oct 2004 23:58:29 -0000	1.14
+++ fticonfig_table_get.hh	5 Nov 2004 22:02:20 -0000
@@ -91,12 +91,12 @@ public:
      * @param fte_list the list with the Fte entries to store the result.
      * @param buf the buffer with the data to parse.
      * @param buf_bytes the size of the data in the buffer.
-     * @param is_rtm_get_only if true, consider only the RTM_GET entries.
+     * @param type the subset of RTM messages that caller is interested in.
      * @return true on success, otherwise false.
      * @see FteX.
      */
     bool parse_buffer_rtm(int family, list<FteX>& fte_list, const uint8_t *buf,
-			  size_t buf_bytes, bool is_rtm_get_only);
+			  size_t buf_bytes, FtiRtmParseType type);
 
     /**
      * Parse information about routing table information received from
Index: fticonfig_table_get_sysctl.cc
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig_table_get_sysctl.cc,v
retrieving revision 1.13
diff -u -p -r1.13 fticonfig_table_get_sysctl.cc
--- fticonfig_table_get_sysctl.cc	1 Sep 2004 18:12:24 -0000	1.13
+++ fticonfig_table_get_sysctl.cc	5 Nov 2004 22:02:20 -0000
@@ -179,7 +179,8 @@ FtiConfigTableGetSysctl::get_table(int f
 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), table_data, &sz, NULL, 0)
 	    == 0) {
 	    // Parse the result
-	    return (parse_buffer_rtm(family, fte_list, table_data, sz, true));
+	    return (parse_buffer_rtm(family, fte_list, table_data, sz,
+				     FtiRtmParseType(GET)));
 	}
 	
 	// Error
Index: fticonfig_table_observer_rtsock.cc
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig_table_observer_rtsock.cc,v
retrieving revision 1.10
diff -u -p -r1.10 fticonfig_table_observer_rtsock.cc
--- fticonfig_table_observer_rtsock.cc	1 Sep 2004 18:12:25 -0000	1.10
+++ fticonfig_table_observer_rtsock.cc	5 Nov 2004 22:02:20 -0000
@@ -93,7 +93,7 @@ FtiConfigTableObserverRtsock::receive_da
     //
     if (ftic().have_ipv4()) {
 	ftic().ftic_table_get_primary().parse_buffer_rtm(AF_INET, fte_list,
-							 data, nbytes, false);
+				 data, nbytes, FtiRtmParseType(CHANGES));
 	if (! fte_list.empty()) {
 	    propagate_fib_changes(fte_list);
 	    fte_list.clear();
@@ -106,7 +106,7 @@ FtiConfigTableObserverRtsock::receive_da
     //
     if (ftic().have_ipv6()) {
 	ftic().ftic_table_get_primary().parse_buffer_rtm(AF_INET6, fte_list,
-							 data, nbytes, false);
+				 data, nbytes, FtiRtmParseType(CHANGES));
 	if (! fte_list.empty()) {
 	    propagate_fib_changes(fte_list);
 	    fte_list.clear();
Index: fticonfig_table_parse_rtm.cc
===================================================================
RCS file: /usr/local/www/data/cvs/xorp/fea/fticonfig_table_parse_rtm.cc,v
retrieving revision 1.10
diff -u -p -r1.10 fticonfig_table_parse_rtm.cc
--- fticonfig_table_parse_rtm.cc	5 Nov 2004 01:27:53 -0000	1.10
+++ fticonfig_table_parse_rtm.cc	5 Nov 2004 22:02:20 -0000
@@ -40,7 +40,7 @@
 #ifndef HAVE_ROUTING_SOCKETS
 bool
 FtiConfigTableGet::parse_buffer_rtm(int, list<FteX>& , const uint8_t* ,
-				    size_t , bool )
+				    size_t , FtiRtmParseType type)
 {
     return false;
 }
@@ -50,13 +50,14 @@ FtiConfigTableGet::parse_buffer_rtm(int,
 bool
 FtiConfigTableGet::parse_buffer_rtm(int family, list<FteX>& fte_list,
 				    const uint8_t* buf, size_t buf_bytes,
-				    bool is_rtm_get_only)
+				    FtiRtmParseType type)
 {
-    const struct rt_msghdr* rtm = reinterpret_cast<const struct rt_msghdr *>(buf);
+    const struct rt_msghdr* rtm =
+	reinterpret_cast<const struct rt_msghdr *>(buf);
     const uint8_t* last = buf + buf_bytes;
-    
+
     for (const uint8_t* ptr = buf; ptr < last; ptr += rtm->rtm_msglen) {
-    	rtm = reinterpret_cast<const struct rt_msghdr *>(ptr);
+	rtm = reinterpret_cast<const struct rt_msghdr *>(ptr);
 	if (RTM_VERSION != rtm->rtm_version) {
 	    XLOG_ERROR("RTM version mismatch: expected %d got %d",
 		       RTM_VERSION,
@@ -64,25 +65,31 @@ FtiConfigTableGet::parse_buffer_rtm(int 
 	    continue;
 	}
 
-	if (is_rtm_get_only) {
-	    //
-	    // Consider only the RTM_GET entries.
-	    //
-	    if (rtm->rtm_type != RTM_GET)
-		continue;
-	    if (! (rtm->rtm_flags & RTF_UP))
+	if (rtm->rtm_errno != 0)
+	    continue;		// XXX: ignore entries with an error
+
+	if (type == FtiRtmParseType(GET)) {
+	    if ((rtm->rtm_type != RTM_GET) || (!(rtm->rtm_flags & RTF_UP)))
 		continue;
 	}
 
-	if ((rtm->rtm_type != RTM_ADD)
-	    && (rtm->rtm_type != RTM_DELETE)
-	    && (rtm->rtm_type != RTM_CHANGE)
-	    && (rtm->rtm_type != RTM_GET)) {
-	    continue;
+	// Upcalls may not be supported in some BSD derived implementations.
+	if (type == FtiRtmParseType(UPCALLS)) {
+#ifdef RTM_MISS
+	    if (rtm->rtm_type != RTM_MISS)
+		continue;
+#endif
+#ifdef RTM_RESOLVE
+	    if (rtm->rtm_type != RTM_RESOLVE)
+		continue;
+#endif
 	}
 
-	if (rtm->rtm_errno != 0)
-	    continue;		// XXX: ignore entries with an error
+	if (type == FtiRtmParseType(UPCALLS)) {
+	    if ((rtm->rtm_type != RTM_ADD) && (rtm->rtm_type != RTM_DELETE) &&
+		(rtm->rtm_type != RTM_CHANGE) && (rtm->rtm_type != RTM_GET))
+		    continue;
+	}
 
 #ifdef RTF_LLINFO
 	if (rtm->rtm_flags & RTF_LLINFO)
@@ -104,12 +111,12 @@ FtiConfigTableGet::parse_buffer_rtm(int 
 	if (rtm->rtm_flags & RTF_BROADCAST)
 	    continue;		// XXX: ignore broadcast entries
 #endif
-	
+
 	FteX fte(family);
 	if (RtmUtils::rtm_get_to_fte_cfg(fte, ftic().iftree(), rtm) == true)
 	    fte_list.push_back(fte);
     }
-    
+
     return true;
 }
 

--WfZ7S8PLGjBY9Voh--