LISP multihoming API changes and cleanup 05/2205/3
authorFlorin Coras <[email protected]>
Tue, 2 Aug 2016 00:31:03 +0000 (02:31 +0200)
committerDave Barach <[email protected]>
Thu, 4 Aug 2016 11:58:07 +0000 (11:58 +0000)
Change-Id: I106352a6da0fad2b91dc8593f8d6d664af3113a8
Signed-off-by: Florin Coras <[email protected]>
vnet/vnet/lisp-cp/control.c
vnet/vnet/lisp-cp/control.h
vnet/vnet/lisp-cp/lisp_types.c
vnet/vnet/lisp-cp/lisp_types.h
vnet/vnet/lisp-gpe/lisp_gpe.c
vnet/vnet/lisp-gpe/lisp_gpe.h
vpp-api-test/vat/api_format.c
vpp/vpp-api/api.c
vpp/vpp-api/vpe.api

index 9b86da5..4424b60 100644 (file)
@@ -221,8 +221,7 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
   /* delete dp fwd entry */
   u32 sw_if_index;
   a->is_add = 0;
-  a->rmt_loc = fe->dst_loc;
-  a->lcl_loc = fe->src_loc;
+  a->locator_pairs = fe->locator_pairs;
   a->vni = gid_address_vni(&a->rmt_eid);
   gid_address_copy(&a->rmt_eid, &fe->deid);
 
@@ -230,6 +229,7 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
 
   /* delete entry in fwd table */
   hash_unset(lcm->fwd_entry_by_mapping_index, dst_map_index);
+  vec_free(fe->locator_pairs);
   pool_put(lcm->fwd_entry_pool, fe);
 }
 
@@ -240,13 +240,14 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
  */
 static u32
 get_locator_pair (lisp_cp_main_t* lcm, mapping_t * lcl_map, mapping_t * rmt_map,
-                  ip_address_t * lcl_loc, ip_address_t * rmt_loc)
+                  locator_pair_t ** locator_pairs)
 {
   u32 i, minp = ~0, limitp = 0, li, check_index = 0, done = 0, esi;
   locator_set_t * rmt_ls, * lcl_ls;
   ip_address_t _lcl, * lcl = &_lcl;
   locator_t * l, * rmt = 0;
   uword * checked = 0;
+  locator_pair_t pair;
 
   rmt_ls = pool_elt_at_index(lcm->locator_set_pool, rmt_map->locator_set_index);
   lcl_ls = pool_elt_at_index(lcm->locator_set_pool, lcl_map->locator_set_index);
@@ -299,8 +300,10 @@ get_locator_pair (lisp_cp_main_t* lcm, mapping_t * lcl_map, mapping_t * rmt_map,
                              gid_address_ip_version(&rmt->address), lcl))
                     continue;
 
-                  ip_address_copy(rmt_loc, &gid_address_ip(&rmt->address));
-                  ip_address_copy(lcl_loc, lcl);
+                  memset(&pair, 0, sizeof(pair));
+                  ip_address_copy(&pair.rmt_loc, &gid_address_ip(&rmt->address));
+                  ip_address_copy(&pair.lcl_loc, lcl);
+                  vec_add1(locator_pairs[0], pair);
                   done = 2;
                 }
             }
@@ -366,7 +369,7 @@ dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
     }
 
   /* find best locator pair that 1) verifies LISP policy 2) are connected */
-  if (0 == get_locator_pair (lcm, src_map, dst_map, &a->lcl_loc, &a->rmt_loc))
+  if (0 == get_locator_pair (lcm, src_map, dst_map, &a->locator_pairs))
     {
       /* negative entry */
       a->is_negative = 1;
@@ -382,8 +385,7 @@ dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
 
   /* add tunnel to fwd entry table XXX check return value from DP insertion */
   pool_get (lcm->fwd_entry_pool, fe);
-  fe->dst_loc = a->rmt_loc;
-  fe->src_loc = a->lcl_loc;
+  fe->locator_pairs = a->locator_pairs;
   gid_address_copy (&fe->deid, &a->rmt_eid);
   hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
             fe - lcm->fwd_entry_pool);
@@ -985,7 +987,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
         is_add = 0;
       else if (unformat (line_input, "add"))
         ;
-      else if (unformat (line_input, "%U", unformat_gid_address, &eid))
+      else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
         eid_set = 1;
       else if (unformat (line_input, "vni %u", &vni))
         {
@@ -1002,7 +1004,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
           curr_rloc->weight = w;
         }
       else if (unformat (line_input, "rloc %U", unformat_ip_address,
-                         &rloc.address))
+                         &gid_address_ip(&rloc.address)))
         {
           vec_add1 (rlocs, rloc);
           curr_rloc = &rlocs[vec_len (rlocs) - 1];
@@ -1025,8 +1027,6 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
 
   if (!del_all)
     {
-
-
       if (is_add && (~0 == action)
           && 0 == vec_len (rlocs))
         {
index 74ade39..ff722fe 100644 (file)
@@ -30,8 +30,7 @@ typedef struct
 {
   gid_address_t seid;
   gid_address_t deid;
-  ip_address_t src_loc;
-  ip_address_t dst_loc;
+  locator_pair_t * locator_pairs;
 } fwd_entry_t;
 
 typedef enum
index e62edb9..ad420a4 100644 (file)
@@ -210,16 +210,15 @@ unformat_gid_address (unformat_input_t * input, va_list * args)
   ip_prefix_t ippref;
 
   memset (&ippref, 0, sizeof (ippref));
-  memset(a, 0, sizeof(a[0]));
 
   if (unformat (input, "%U", unformat_ip_prefix, &ippref))
     {
-      clib_memcpy (&gid_address_ippref(a), &ippref, sizeof(ippref));
+      ip_prefix_copy (&gid_address_ippref(a), &ippref);
       gid_address_type(a) = GID_ADDR_IP_PREFIX;
     }
   else if (unformat (input, "%U", unformat_mac_address, mac))
     {
-      clib_memcpy (gid_address_mac(a), mac, sizeof(mac));
+      mac_copy (gid_address_mac(a), mac);
       gid_address_type(a) = GID_ADDR_MAC;
     }
   else if (unformat (input, "[%d]", &vni))
index b1b4b9d..6542b00 100644 (file)
@@ -252,4 +252,25 @@ typedef struct
 uword
 unformat_negative_mapping_action (unformat_input_t * input, va_list * args);
 
+/* dp works with a subset of ids */
+typedef struct lisp_dp_address
+{
+  union
+  {
+    ip_prefix_t ippref;
+    u8 mac[6];
+  };
+  u8 type;
+} dp_address_t;
+
+typedef struct locator_pair
+{
+  /* local and remote locators (underlay attachment points) */
+  ip_address_t lcl_loc;
+  ip_address_t rmt_loc;
+
+  u8 priority;
+  u8 weight;
+} locator_pair_t;
+
 #endif /* VNET_LISP_GPE_LISP_TYPES_H_ */
index 812e0ae..ae3a5e0 100644 (file)
@@ -113,12 +113,10 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2,
 
   /* fill in the key's remote eid */
   if (!is_l2)
-    ip_prefix_copy (&key.rmt_ippref, &gid_address_ippref(&a->rmt_eid));
+    ip_prefix_copy (&key.rmt.ippref, &gid_address_ippref(&a->rmt_eid));
   else
-    mac_copy (&key.rmt_mac, &gid_address_mac(&a->rmt_eid));
+    mac_copy (&key.rmt.mac, &gid_address_mac(&a->rmt_eid));
 
-
-  ip_address_copy(&key.rmt_loc, &a->rmt_loc);
   key.vni = clib_host_to_net_u32 (a->vni);
 
   p = mhash_get (&lgm->lisp_gpe_tunnel_by_key, &key);
@@ -140,8 +138,12 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2,
       foreach_copy_field;
 #undef _
 
-      ip_address_copy(&t->src, &a->lcl_loc);
-      ip_address_copy(&t->dst, &a->rmt_loc);
+      /* TODO multihoming */
+      if (!a->is_negative)
+        {
+          ip_address_copy (&t->src, &a->locator_pairs[0].lcl_loc);
+          ip_address_copy (&t->dst, &a->locator_pairs[0].rmt_loc);
+        }
 
       /* if vni is non-default */
       if (a->vni)
@@ -152,7 +154,7 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2,
 
       /* next proto */
       if (!is_l2)
-        t->next_protocol = ip_prefix_version(&key.rmt_ippref) == IP4 ?
+        t->next_protocol = ip_prefix_version(&key.rmt.ippref) == IP4 ?
                 LISP_GPE_NEXT_PROTO_IP4 : LISP_GPE_NEXT_PROTO_IP6;
       else
         t->next_protocol = LISP_GPE_NEXT_PROTO_ETHERNET;
@@ -194,94 +196,29 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2,
 }
 
 static int
-add_del_negative_ip_fwd_entry (lisp_gpe_main_t * lgm,
-                            vnet_lisp_gpe_add_del_fwd_entry_args_t * a)
-{
-  ip_adjacency_t adj;
-  ip_prefix_t * dpref = &gid_address_ippref(&a->rmt_eid);
-  ip_prefix_t * spref = &gid_address_ippref(&a->lcl_eid);
-
-  /* setup adjacency for eid */
-  memset (&adj, 0, sizeof(adj));
-  adj.n_adj = 1;
-
-  /* fill in 'legal' data to avoid issues */
-  adj.lookup_next_index =  (ip_prefix_version(dpref) == IP4) ?
-                                  lgm->ip4_lookup_next_lgpe_ip4_lookup :
-                                  lgm->ip6_lookup_next_lgpe_ip6_lookup;
-
-  adj.rewrite_header.sw_if_index = ~0;
-  adj.rewrite_header.next_index = ~0;
-
-  switch (a->action)
-    {
-    case LISP_NO_ACTION:
-      /* TODO update timers? */
-    case LISP_FORWARD_NATIVE:
-      /* TODO check if route/next-hop for eid exists in fib and add
-       * more specific for the eid with the next-hop found */
-    case LISP_SEND_MAP_REQUEST:
-      /* insert tunnel that always sends map-request */
-      adj.explicit_fib_index = (ip_prefix_version(dpref) == IP4) ?
-                               LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP:
-                               LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
-      /* add/delete route for prefix */
-      return ip_sd_fib_add_del_route (lgm, dpref, spref, a->table_id, &adj,
-                                      a->is_add);
-    case LISP_DROP:
-      /* for drop fwd entries, just add route, no need to add encap tunnel */
-      adj.explicit_fib_index =  (ip_prefix_version(dpref) == IP4 ?
-              LGPE_IP4_LOOKUP_NEXT_DROP : LGPE_IP6_LOOKUP_NEXT_DROP);
-
-      /* add/delete route for prefix */
-      return ip_sd_fib_add_del_route (lgm, dpref, spref, a->table_id, &adj,
-                                      a->is_add);
-    default:
-      return -1;
-    }
-}
-
-static int
-add_del_ip_fwd_entry (lisp_gpe_main_t * lgm,
-                      vnet_lisp_gpe_add_del_fwd_entry_args_t * a)
+build_ip_adjacency (lisp_gpe_main_t * lgm, ip_adjacency_t * adj, u32 table_id,
+                    u32 vni, u32 tun_index, u8 is_negative, u8 action,
+                    u8 ip_ver)
 {
-  ip_adjacency_t adj, * adjp;
-  u32 adj_index, rv, tun_index = ~0;
-  ip_prefix_t * dpref, * spref;
   uword * lookup_next_index, * lgpe_sw_if_index, * lnip;
-  u8 ip_ver;
-
-  /* treat negative fwd entries separately */
-  if (a->is_negative)
-    return add_del_negative_ip_fwd_entry (lgm, a);
-
-  /* add/del tunnel to tunnels pool and prepares rewrite */
-  rv = add_del_ip_tunnel (a, 0 /* is_l2 */, &tun_index);
-  if (rv)
-    return rv;
-
-  dpref = &gid_address_ippref(&a->rmt_eid);
-  spref = &gid_address_ippref(&a->lcl_eid);
-  ip_ver = ip_prefix_version(dpref);
-
-  /* setup adjacency for eid */
-  memset (&adj, 0, sizeof(adj));
-  adj.n_adj = 1;
 
+  memset(adj, 0, sizeof(adj[0]));
+  adj->n_adj = 1;
   /* fill in lookup_next_index with a 'legal' value to avoid problems */
-  adj.lookup_next_index = (ip_ver == IP4) ?
+  adj->lookup_next_index = (ip_ver == IP4) ?
           lgm->ip4_lookup_next_lgpe_ip4_lookup :
           lgm->ip6_lookup_next_lgpe_ip6_lookup;
 
-  if (a->is_add)
+  /* positive mapping */
+  if (!is_negative)
     {
       /* send packets that hit this adj to lisp-gpe interface output node in
        * requested vrf. */
       lnip = (ip_ver == IP4) ?
               lgm->lgpe_ip4_lookup_next_index_by_table_id :
               lgm->lgpe_ip6_lookup_next_index_by_table_id;
-      lookup_next_index = hash_get(lnip, a->table_id);
-      lgpe_sw_if_index = hash_get(lgm->l3_ifaces.sw_if_index_by_vni, a->vni);
+      lookup_next_index = hash_get(lnip, table_id);
+      lgpe_sw_if_index = hash_get(lgm->l3_ifaces.sw_if_index_by_vni, vni);
 
       /* the assumption is that the interface must've been created before
        * programming the dp */
@@ -290,19 +227,84 @@ add_del_ip_fwd_entry (lisp_gpe_main_t * lgm,
 
       /* hijack explicit fib index to store lisp interface node index and
        * if_address_index for the tunnel index */
-      adj.explicit_fib_index = lookup_next_index[0];
-      adj.if_address_index = tun_index;
-      adj.rewrite_header.sw_if_index = lgpe_sw_if_index[0];
+      adj->explicit_fib_index = lookup_next_index[0];
+      adj->if_address_index = tun_index;
+      adj->rewrite_header.sw_if_index = lgpe_sw_if_index[0];
+    }
+  /* negative mapping */
+  else
+    {
+      adj->rewrite_header.sw_if_index = ~0;
+      adj->rewrite_header.next_index = ~0;
+
+      switch (action)
+        {
+        case LISP_NO_ACTION:
+          /* TODO update timers? */
+        case LISP_FORWARD_NATIVE:
+          /* TODO check if route/next-hop for eid exists in fib and add
+           * more specific for the eid with the next-hop found */
+        case LISP_SEND_MAP_REQUEST:
+          /* insert tunnel that always sends map-request */
+          adj->explicit_fib_index = (ip_ver == IP4) ?
+                                   LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP:
+                                   LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
+          break;
+        case LISP_DROP:
+          /* for drop fwd entries, just add route, no need to add encap tunnel */
+          adj->explicit_fib_index =  (ip_ver == IP4 ?
+                  LGPE_IP4_LOOKUP_NEXT_DROP : LGPE_IP6_LOOKUP_NEXT_DROP);
+          break;
+        default:
+          return -1;
+        }
+    }
+  return 0;
+}
+
+static int
+add_del_ip_fwd_entry (lisp_gpe_main_t * lgm,
+                      vnet_lisp_gpe_add_del_fwd_entry_args_t * a)
+{
+  ip_adjacency_t adj, * adjp;
+  u32 rv, tun_index = ~0;
+  ip_prefix_t * rmt_pref, * lcl_pref;
+  u8 ip_ver;
+
+  rmt_pref = &gid_address_ippref(&a->rmt_eid);
+  lcl_pref = &gid_address_ippref(&a->lcl_eid);
+  ip_ver = ip_prefix_version(rmt_pref);
+
+  /* add/del tunnel to tunnels pool and prepares rewrite */
+  if (!a->is_negative)
+    {
+      rv = add_del_ip_tunnel (a, 0 /* is_l2 */, &tun_index);
+      if (rv)
+        {
+          clib_warning ("failed to build tunnel!");
+          return rv;
+        }
     }
 
-  /* add/delete route for prefix */
-  rv = ip_sd_fib_add_del_route (lgm, dpref, spref, a->table_id, &adj,
+  /* setup adjacency for eid */
+  rv = build_ip_adjacency (lgm, &adj, a->table_id, a->vni, tun_index,
+                           a->is_negative, a->action, ip_ver);
+
+  /* add/delete route for eid */
+  rv |= ip_sd_fib_add_del_route (lgm, rmt_pref, lcl_pref, a->table_id, &adj,
                                 a->is_add);
 
+  if (rv)
+    {
+      clib_warning ("failed to insert route for tunnel!");
+      return rv;
+    }
+
   /* check that everything worked */
   if (CLIB_DEBUG && a->is_add)
     {
-      adj_index = ip_sd_fib_get_route (lgm, dpref, spref, a->table_id);
+      u32 adj_index;
+      adj_index = ip_sd_fib_get_route (lgm, rmt_pref, lcl_pref, a->table_id);
       ASSERT(adj_index != 0);
 
       adjp = ip_get_adjacency ((ip_ver == IP4) ? lgm->lm4 : lgm->lm6,
@@ -438,11 +440,12 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm,
 {
   unformat_input_t _line_input, * line_input = &_line_input;
   u8 is_add = 1;
-  ip_address_t lloc, rloc, *llocs = 0, *rlocs = 0;
+  ip_address_t lloc, rloc;
   clib_error_t * error = 0;
   gid_address_t _reid, * reid = &_reid, _leid, * leid = &_leid;
   u8 reid_set = 0, leid_set = 0, is_negative = 0, vrf_set = 0, vni_set = 0;
-  u32 vni, vrf, action = ~0;
+  u32 vni, vrf, action = ~0, p, w;
+  locator_pair_t pair, * pairs = 0;
   int rv;
 
   /* Get a line of input. */
@@ -480,13 +483,15 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm,
         {
           is_negative = 1;
         }
-      else if (unformat (line_input, "lloc %U rloc %U",
+      else if (unformat (line_input, "loc-pair %U %U p %d w %d",
                          unformat_ip_address, &lloc,
-                         unformat_ip_address, &rloc))
+                         unformat_ip_address, &rloc, &p, &w))
         {
-          /* TODO: support p and w */
-          vec_add1 (llocs, lloc);
-          vec_add1 (rlocs, rloc);
+          pair.lcl_loc = lloc;
+          pair.rmt_loc = rloc;
+          pair.priority = p;
+          pair.weight = w;
+          vec_add1(pairs, pair);
         }
       else
         {
@@ -518,17 +523,11 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm,
     }
   else
     {
-      if (vec_len (llocs) == 0)
+      if (vec_len (pairs) == 0)
         {
           error = clib_error_return (0, "expected ip4/ip6 locators.");
           goto done;
         }
-
-      if (vec_len (llocs) != 1)
-        {
-          error = clib_error_return (0, "multihoming not supported for now!");
-          goto done;
-        }
     }
 
 
@@ -550,12 +549,7 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm,
   a->table_id = vrf;
   gid_address_copy(&a->lcl_eid, leid);
   gid_address_copy(&a->rmt_eid, reid);
-
-  if (!is_negative)
-    {
-      a->lcl_loc = llocs[0];
-      a->rmt_loc = rlocs[0];
-    }
+  a->locator_pairs = pairs;
 
   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
   if (0 != rv)
@@ -565,8 +559,7 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm,
     }
 
  done:
-  vec_free(llocs);
-  vec_free(rlocs);
+  vec_free(pairs);
   return error;
 }
 
@@ -699,12 +692,20 @@ vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a)
         vec_add1(tunnels, tunnel[0]);
       }));
 
-      vec_foreach(tunnel, tunnels) {
+      vec_foreach(tunnel, tunnels)
+      {
         memset(at, 0, sizeof(at[0]));
         at->is_add = 0;
-        gid_address_type(&at->rmt_eid) = GID_ADDR_IP_PREFIX;
-        ip_prefix_copy(&gid_address_ippref(&at->rmt_eid), &tunnel->rmt_ippref);
-        ip_address_copy(&at->rmt_loc, &tunnel->rmt_loc);
+        if (tunnel->rmt.type == GID_ADDR_IP_PREFIX)
+          {
+            gid_address_type(&at->rmt_eid) = GID_ADDR_IP_PREFIX;
+            ip_prefix_copy(&gid_address_ippref(&at->rmt_eid), &tunnel->rmt.ippref);
+          }
+        else
+          {
+            gid_address_type(&at->rmt_eid) = GID_ADDR_MAC;
+            mac_copy(&gid_address_mac(&at->rmt_eid), &tunnel->rmt.mac);
+          }
         vnet_lisp_gpe_add_del_fwd_entry (at, 0);
       }
       vec_free(tunnels);
index c3f0242..f3e7577 100644 (file)
@@ -46,13 +46,8 @@ typedef struct
   {
     struct
     {
-      /* within the dp only ip and mac can be eids */
-      union
-      {
-        ip_prefix_t rmt_ippref;
-        u8 rmt_mac[6];
-      };
-      ip_address_t rmt_loc;
+      dp_address_t rmt;
+      dp_address_t lcl;
       u32 vni;
     };
     u8 as_u8[40];
@@ -246,9 +241,8 @@ typedef struct
   gid_address_t lcl_eid;
   gid_address_t rmt_eid;
 
-  /* local and remote locators (underlay attachment points) */
-  ip_address_t lcl_loc;
-  ip_address_t rmt_loc;
+  /* vector of locator pairs */
+  locator_pair_t * locator_pairs;
 
   /* FIB indices to lookup remote locator at encap and inner IP at decap */
   u32 encap_fib_index;
index d410955..051f95f 100644 (file)
@@ -10958,6 +10958,7 @@ api_lisp_gpe_add_del_fwd_entry(vat_main_t * vam)
     mp->eid_type = rmt_eid->type;
     mp->rmt_len = rmt_eid->len;
     mp->lcl_len = lcl_eid->len;
+    mp->action = action;
 
     mp->loc_num = vec_len (rmt_locs);
     clib_memcpy (mp->lcl_locs, lcl_locs,
index 18999a5..45c3aeb 100644 (file)
@@ -4975,23 +4975,51 @@ typedef CLIB_PACKED(struct
   u8 addr[16]; /**< IPv4/IPv6 address */
 }) rloc_t;
 
+static locator_pair_t *
+unformat_lisp_loc_pairs (void * lcl_locs, void * rmt_locs, u32 rloc_num)
+{
+  u32 i;
+  locator_pair_t * pairs = 0, pair;
+  rloc_t * r;
+
+  for (i = 0; i < rloc_num; i++) {
+      /* local locator */
+      r = &((rloc_t *) lcl_locs)[i];
+      memset(&pair.lcl_loc, 0, sizeof(pair.lcl_loc));
+      ip_address_set(&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
+
+      /* remote locators */
+      r = &((rloc_t *) rmt_locs)[i];
+      memset(&pair.rmt_loc, 0, sizeof(pair.rmt_loc));
+      ip_address_set(&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
+
+      pair.priority = r->priority;
+      pair.weight = r->weight;
+
+      vec_add1 (pairs, pair);
+  }
+  return pairs;
+}
+
 static locator_t *
-unformat_lisp_locs (void * data, u32 rloc_num)
+unformat_lisp_locs (void * rmt_locs, u32 rloc_num)
 {
   u32 i;
-  locator_t rloc, * rlocs = 0;
+  locator_t * locs = 0, loc;
+  rloc_t * r;
 
   for (i = 0; i < rloc_num; i++) {
-      rloc_t * r = &((rloc_t *) data)[i];
-      memset(&rloc, 0, sizeof(rloc));
-      gid_address_ip_set (&rloc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
-      gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128;
-      gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX;
-      rloc.priority = r->priority;
-      rloc.weight = r->weight;
-      vec_add1 (rlocs, rloc);
+      /* remote locators */
+      r = &((rloc_t *) rmt_locs)[i];
+      memset(&loc, 0, sizeof(loc));
+      gid_address_ip_set(&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
+
+      loc.priority = r->priority;
+      loc.weight = r->weight;
+
+      vec_add1 (locs, loc);
   }
-  return rlocs;
+  return locs;
 }
 
 static void
@@ -4999,9 +5027,9 @@ vl_api_lisp_gpe_add_del_fwd_entry_t_handler(
     vl_api_lisp_gpe_add_del_fwd_entry_t *mp)
 {
     vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
-    int rv = 0;
     vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
-    locator_t * lcl_locs = 0, * rmt_locs = 0;
+    locator_pair_t * pairs = 0;
+    int rv = 0;
 
     memset (a, 0, sizeof(a[0]));
 
@@ -5010,20 +5038,19 @@ vl_api_lisp_gpe_add_del_fwd_entry_t_handler(
     rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
                                  mp->lcl_eid, mp->lcl_len);
 
-    lcl_locs = unformat_lisp_locs (mp->lcl_locs, mp->loc_num);
-    rmt_locs = unformat_lisp_locs (mp->rmt_locs, mp->loc_num);
+    pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
 
-    if (rv || 0 == lcl_locs || 0 == lcl_locs)
+    if (rv || 0 == pairs)
       goto send_reply;
 
     a->is_add = mp->is_add;
-    a->lcl_loc = gid_address_ip(&lcl_locs[0].address); /* TODO support more */
-    a->rmt_loc = gid_address_ip(&rmt_locs[0].address);
+    a->locator_pairs = pairs;
     a->dp_table = mp->dp_table;
     a->vni = mp->vni;
+    a->action = mp->action;
 
     rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
-
+    vec_free(pairs);
 send_reply:
     REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
 }
index 4b8aa81..810d86d 100644 (file)
@@ -2278,6 +2278,7 @@ define lisp_add_del_local_eid_reply {
     @param loc_num - number of locators
     @param lcl_locs - array of local locators
     @param rmt_locs - array of remote locators
+    @param action - negative action when 0 locators configured
 */
 define lisp_gpe_add_del_fwd_entry {
     u32 client_index;
@@ -2287,12 +2288,13 @@ define lisp_gpe_add_del_fwd_entry {
     u8  rmt_eid[16];
     u8  lcl_eid[16];
     u8  rmt_len;
-    u8  lcl_len;    
+    u8  lcl_len;
     u32 vni;
     u32 dp_table;
     u32 loc_num;
     u8  lcl_locs[loc_num];
     u8  rmt_locs[loc_num];
+    u8  action;
 };
 
 /** \brief Reply for gpe_fwd_entry add/del