fib: only update glean for interface if necessary

Type: improvement

If an interface address is added, the glean adjacency for it's covering
prefix is updated with that address. In the case of multiple addresses
within the same prefix being added, the most recently added one will end
up being used as the sender protocol address for ARP requests.

Similar behavior occurs when an interface address is deleted. The glean
adjacency is updated to some appropriate entry under it's covering
prefix. If there were multiple interface addresses configured, we may
update the address on the adjacency even though the address currently in
use is not the one being deleted.

Add a new value PROVIDES_GLEAN to fib_entry_src_flag_t. The flag
identifies whether a source interface entry is being used as the address
for the glean adjacency for the covering prefix.

Update logic so that the glean is only updated on adding an interface
address if there is not already a sibling entry in use which has the
flag set. Also, only update the glean on deleting an interface address
if the address being deleted has the flag set.

Also update unit test which validates expected behavior in the case
where multiple addresses within a prefix are configured on an interface.

Signed-off-by: Matthew Smith <mgsmith@netgate.com>
Change-Id: I7d918b8dd703735b20ec76e0a60af6d7e571b766
diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h
index 2239283..7331f80 100644
--- a/src/vnet/fib/fib_entry.h
+++ b/src/vnet/fib/fib_entry.h
@@ -154,9 +154,13 @@
      */
     FIB_ENTRY_SRC_ATTRIBUTE_INHERITED,
     /**
+     * the source is currently used as glean src address
+     */
+    FIB_ENTRY_SRC_ATTRIBUTE_PROVIDES_GLEAN,
+    /**
      * Marker. add new entries before this one.
      */
-    FIB_ENTRY_SRC_ATTRIBUTE_LAST = FIB_ENTRY_SRC_ATTRIBUTE_INHERITED,
+    FIB_ENTRY_SRC_ATTRIBUTE_LAST = FIB_ENTRY_SRC_ATTRIBUTE_PROVIDES_GLEAN,
 } fib_entry_src_attribute_t;
 
 
@@ -166,6 +170,7 @@
     [FIB_ENTRY_SRC_ATTRIBUTE_ACTIVE] = "active", \
     [FIB_ENTRY_SRC_ATTRIBUTE_STALE] = "stale",      \
     [FIB_ENTRY_SRC_ATTRIBUTE_INHERITED] = "inherited", \
+    [FIB_ENTRY_SRC_ATTRIBUTE_PROVIDES_GLEAN] = "provides-glean", \
 }
 
 #define FOR_EACH_FIB_SRC_ATTRIBUTE(_item)      		\
@@ -180,6 +185,7 @@
     FIB_ENTRY_SRC_FLAG_ACTIVE = (1 << FIB_ENTRY_SRC_ATTRIBUTE_ACTIVE),
     FIB_ENTRY_SRC_FLAG_STALE = (1 << FIB_ENTRY_SRC_ATTRIBUTE_STALE),
     FIB_ENTRY_SRC_FLAG_INHERITED = (1 << FIB_ENTRY_SRC_ATTRIBUTE_INHERITED),
+    FIB_ENTRY_SRC_FLAG_PROVIDES_GLEAN = (1 << FIB_ENTRY_SRC_ATTRIBUTE_PROVIDES_GLEAN),
 } __attribute__ ((packed)) fib_entry_src_flag_t;
 
 extern u8 * format_fib_entry_src_flags(u8 *s, va_list *args);