Fix MAP-E UT. Add functionality in MAP code to delete the pre-resolved next-hops. UT checks for no-leftover-state now pass

Change-Id: I9e980ee117c0b6aebc6c7a0fcc153a7c0eaf0c72
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/map/map.c b/src/vnet/map/map.c
index 6823a46..7006b1d 100644
--- a/src/vnet/map/map.c
+++ b/src/vnet/map/map.c
@@ -556,23 +556,51 @@
 }
 
 static void
-map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6)
+map_fib_unresolve (map_main_pre_resolved_t * pr,
+		   fib_protocol_t proto, u8 len, const ip46_address_t * addr)
+{
+  fib_prefix_t pfx = {
+    .fp_proto = proto,
+    .fp_len = len,
+    .fp_addr = *addr,
+  };
+
+  fib_entry_child_remove (pr->fei, pr->sibling);
+
+  fib_table_entry_special_remove (0,	// default fib
+				  &pfx, FIB_SOURCE_RR);
+  dpo_reset (&pr->dpo);
+
+  pr->fei = FIB_NODE_INDEX_INVALID;
+  pr->sibling = FIB_NODE_INDEX_INVALID;
+}
+
+static void
+map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6, int is_del)
 {
   if (ip6 && (ip6->as_u64[0] != 0 || ip6->as_u64[1] != 0))
     {
       ip46_address_t addr = {
 	.ip6 = *ip6,
       };
-      map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP6],
-		       FIB_PROTOCOL_IP6, 128, &addr);
+      if (is_del)
+	map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP6],
+			   FIB_PROTOCOL_IP6, 128, &addr);
+      else
+	map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP6],
+			 FIB_PROTOCOL_IP6, 128, &addr);
     }
   if (ip4 && (ip4->as_u32 != 0))
     {
       ip46_address_t addr = {
 	.ip4 = *ip4,
       };
-      map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP4],
-		       FIB_PROTOCOL_IP4, 32, &addr);
+      if (is_del)
+	map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP4],
+			   FIB_PROTOCOL_IP4, 32, &addr);
+      else
+	map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP4],
+			 FIB_PROTOCOL_IP4, 32, &addr);
     }
 }
 #endif
@@ -817,6 +845,7 @@
   ip4_address_t ip4nh, *p_v4 = NULL;
   ip6_address_t ip6nh, *p_v6 = NULL;
   clib_error_t *error = NULL;
+  int is_del = 0;
 
   memset (&ip4nh, 0, sizeof (ip4nh));
   memset (&ip6nh, 0, sizeof (ip6nh));
@@ -832,6 +861,8 @@
       else
 	if (unformat (line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh))
 	p_v6 = &ip6nh;
+      else if (unformat (line_input, "del"))
+	is_del = 1;
       else
 	{
 	  error = clib_error_return (0, "unknown input `%U'",
@@ -840,7 +871,7 @@
 	}
     }
 
-  map_pre_resolve (p_v4, p_v6);
+  map_pre_resolve (p_v4, p_v6, is_del);
 
 done:
   unformat_free (line_input);
diff --git a/test/test_map.py b/test/test_map.py
index 6bcd70e..9ac3948 100644
--- a/test/test_map.py
+++ b/test/test_map.py
@@ -62,7 +62,6 @@
         self.assertEqual(rx[IPv6].src, ip6_src)
         self.assertEqual(rx[IPv6].dst, ip6_dst)
 
-    @unittest.skip("Doesn't Work")
     def test_map_e(self):
         """ MAP-E """
 
@@ -155,18 +154,21 @@
         #
         # change the route to the pre-solved next-hop
         #
-        pre_res_route1 = VppIpRoute(self,
-                                    "4001::1",
-                                    128,
-                                    [VppRoutePath(self.pg1.remote_hosts[3].ip6,
-                                                  self.pg1.sw_if_index,
-                                                  is_ip6=1)],
-                                    is_ip6=1)
-        pre_res_route1.add_vpp_config()
+        pre_res_route.modify([VppRoutePath(self.pg1.remote_hosts[3].ip6,
+                                           self.pg1.sw_if_index,
+                                           is_ip6=1)])
+        pre_res_route.add_vpp_config()
 
         self.send_and_assert_encapped(v4, map_src,
                                       "2001::c0a8:0:0",
                                       dmac=self.pg1.remote_hosts[3].mac)
 
+        #
+        # cleanup. The test infra's object registry will ensure
+        # the route is really gone and thus that the unresolve worked.
+        #
+        pre_res_route.remove_vpp_config()
+        self.vapi.ppcli("map params pre-resolve del ip6-nh 4001::1")
+
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py
index 7a62b23..e1c2b4b 100644
--- a/test/vpp_ip_route.py
+++ b/test/vpp_ip_route.py
@@ -79,6 +79,13 @@
         else:
             self.dest_addr = inet_pton(AF_INET, dest_addr)
 
+    def modify(self, paths, is_local=0,
+               is_unreach=0, is_prohibit=0):
+        self.paths = paths
+        self.is_local = is_local
+        self.is_unreach = is_unreach
+        self.is_prohibit = is_prohibit
+
     def add_vpp_config(self):
         if self.is_local or self.is_unreach or self.is_prohibit:
             self._test.vapi.ip_add_del_route(
@@ -126,7 +133,8 @@
                                                  path.nh_addr,
                                                  path.nh_itf,
                                                  table_id=self.table_id,
-                                                 is_add=0)
+                                                 is_add=0,
+                                                 is_ipv6=self.is_ip6)
 
     def query_vpp_config(self):
         return find_route(self._test,