summaryrefslogtreecommitdiffstats
path: root/test/remote_test.py
AgeCommit message (Collapse)AuthorFilesLines
2019-04-10Tests Cleanup: Fix missing calls to setUpClass/tearDownClass.Paul Vinciguerra1-0/+4
Continuation/Part 2 of https://gerrit.fd.io/r/#/c/17092/ Change-Id: Id0122d84eaf2c05d29e5be63a594d5e528ee7c9a Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2019-03-28Typos. A bunch of typos I've been collecting.Paul Vinciguerra1-1/+1
Change-Id: I53ab8d17914e6563110354e4052109ac02bf8f3b Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2019-03-15Revert "API: Cleanup APIs interface.api"Ole Trøan1-11/+4
This reverts commit e63325e3ca03c847963863446345e6c80a2c0cfd. Allow time for CSIT to accommodate. Change-Id: I59435e4ab5e05e36a2796c3bf44889b5d4823cc2 Signed-off-by: ot@cisco.com
2019-03-15API: Cleanup APIs interface.apiJakub Grajciar1-4/+11
Use of consistent API types for interface.api Change-Id: Ieb54cebb4ac96b432a3f0b41596718aa2f34885b Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
2019-03-11Tests: remote_test.py. Private member test catching dunder names.Paul Vinciguerra1-9/+14
Private member check also catches __iter__, since it starts with '_'. Fixes: Captured traceback: ~~~~~~~~~~~~~~~~~~ b'Traceback (most recent call last):' b' File "/vpp/test/test_memif.py", line 47, in tearDown' b' remove_all_memif_vpp_config(self.remote_test)' b' File "/vpp/test/vpp_memif.py", line 36, in remove_all_memif_vpp_config' b' for d in dump:' b"TypeError: 'SerializableClassCopy' object is not iterable" b'' Change-Id: I6a3f3e0f2b1b2d0a2b97faa23bf542ff8f92de43 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2019-03-11Tests: 'Fix' __del__ in test/remote_test.py.Paul Vinciguerra1-4/+6
This is not a fix as much as supressing a warning. __del__ is not a destructor. test/remote_test.py:385:13: F821 undefined name 'cls' cls.vpp.poll() ^ test/remote_test.py:386:16: F821 undefined name 'cls' if cls.vpp.returncode is None: ^ test/remote_test.py:387:17: F821 undefined name 'cls' cls.vpp.terminate() ^ test/remote_test.py:388:17: F821 undefined name 'cls' cls.vpp.communicate() Change-Id: I6f0ecf3ae5dee7f279a4e25994cc1c49470bca26 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2019-02-25Remote Test: fix serialization (dict, Enum)Jakub Grajciar1-0/+24
Change-Id: Ia3f8616cbf424c7f2d29d16cf7a457be6cd1b33a Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
2018-11-28test/remote_test.py: Fix missing importPaul Vinciguerra1-0/+1
Change-Id: I192c33d36f43ae2df0dda509e118f2b920d561ac Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2018-11-27VPP-1508 python3 tests: use six.iteritemsPaul Vinciguerra1-1/+1
This replaces dictionary.iteritems() on Python 2 and dictionary.items() on Python 3. Change-Id: I58a3ded7d284c59e28d484b0c285aac435bfc229 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2018-11-27VPP-1508 Fix for bug introduced in tests on use of repr.Paul Vinciguerra1-3/+3
This fixes the change from https://gerrit.fd.io/r/#/c/16175/ ... ====== Totals ====== Ran: 856 tests in 2123.0000 sec. - Passed: 667 - Skipped: 157 - Expected Fail: 0 - Unexpected Success: 0 - Failed: 32 Sum of execute time for each test: 1641.0832 sec. ============== Worker Balance ============== - Worker 0 (416 tests) => 0:35:06.788054 - Worker 1 (440 tests) => 0:31:13.814911 Test id Runtime (s) -------------------------------------------------------------------------------------- ----------- test.test_vcl.VCLCutThruTestCase.test_ldp_cut_thru_bi_dir_nsock 120.382 test.test_vcl.VCLThruHostStackGroupBTestCase.test_ldp_thru_host_stack_bi_dir_nsock 60.368 test.test_vcl.VCLIpv6ThruHostStackGroupBTestCase.test_ldp_thru_host_stack_bi_dir_nsock 60.356 test.test_igmp.TestIgmp.test_igmp_host 47.411 test.test_reassembly.TestFIFReassembly.test_fif6 38.561 test.test_reassembly.TestFIFReassembly.test_fif4 37.045 test.test_gbp.TestGBP.test_gbp 30.041 test.test_dhcp.TestDHCP.test_dhcp_proxy 29.339 test.test_vcl.VCLCutThruTestCase.test_ldp_cut_thru_iperf3 20.489 test.test_neighbor.ARPTestCase.test_arp 19.004 Change-Id: Ic1565f14962f157d5041230de3aeeab0b85f21e1 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2018-11-25VPP-1508 python3 tests: python3 repr.Paul Vinciguerra1-4/+7
Use six.reprlib. Uses repr for python 2 and reprlib for python 3. Change-Id: Ia343a492d533bd511ed57166381e10a37e452d36 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2018-09-27memif: Memif Test CaseJakub Grajciar1-0/+380
Change-Id: Ic0d5fc6ccbd496afcc870b908ef799af7c804c30 Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
* Keyword.Pseudo */ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ .highlight .kt { color: #66d9ef } /* Keyword.Type */ .highlight .ld { color: #e6db74 } /* Literal.Date */ .highlight .m { color: #ae81ff } /* Literal.Number */ .highlight .s { color: #e6db74 } /* Literal.String */ .highlight .na { color: #a6e22e } /* Name.Attribute */ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ .highlight .nc { color: #a6e22e } /* Name.Class */ .highlight .no { color: #66d9ef } /* Name.Constant */ .highlight .nd { color: #a6e22e } /* Name.Decorator */ .highlight .ni { color: #f8f8f2 } /* Name.Entity */ .highlight .ne { color: #a6e22e } /* Name.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * Copyright (c) 2016 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <vnet/lisp-cp/lisp_msg_serdes.h>
#include <vnet/lisp-cp/packets.h>
#include <vppinfra/time.h>

void *lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid);

static void
lisp_msg_put_locators (vlib_buffer_t * b, locator_t * locators)
{
  locator_t *loc;

  vec_foreach (loc, locators)
  {
    u8 *p = vlib_buffer_put_uninit (b, sizeof (locator_hdr_t));
    memset (p, 0, sizeof (locator_hdr_t));
    LOC_PRIORITY (p) = loc->priority;
    LOC_MPRIORITY (p) = loc->mpriority;
    LOC_WEIGHT (p) = loc->weight;
    LOC_MWEIGHT (p) = loc->mweight;
    LOC_LOCAL (p) = loc->local;
    LOC_PROBED (p) = loc->probed ? 1 : 0;
    lisp_msg_put_gid (b, &loc->address);
  }
}

static void
lisp_msg_put_mapping_record (vlib_buffer_t * b, mapping_t * record)
{
  mapping_record_hdr_t *p =
    vlib_buffer_put_uninit (b, sizeof (mapping_record_hdr_t));
  gid_address_t *eid = &record->eid;

  memset (p, 0, sizeof (*p));
  MAP_REC_EID_PLEN (p) = gid_address_len (eid);
  MAP_REC_TTL (p) = clib_host_to_net_u32 (MAP_REGISTER_DEFAULT_TTL);
  MAP_REC_AUTH (p) = record->authoritative ? 1 : 0;
  MAP_REC_LOC_COUNT (p) = vec_len (record->locators);

  lisp_msg_put_gid (b, eid);
  lisp_msg_put_locators (b, record->locators);
}

static void
lisp_msg_put_mreg_records (vlib_buffer_t * b, mapping_t * records)
{
  u32 i;
  for (i = 0; i < vec_len (records); i++)
    lisp_msg_put_mapping_record (b, &records[i]);
}

void *
lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid)
{
  u8 *p = 0;
  if (!gid)
    {
      /* insert only src-eid-afi field set to 0 */
      p = vlib_buffer_put_uninit (b, sizeof (u16));
      *(u16 *) p = 0;
    }
  else
    {
      p = vlib_buffer_put_uninit (b, gid_address_size_to_put (gid));
      gid_address_put (p, gid);
    }
  return p;
}

static void *
lisp_msg_put_itr_rlocs (lisp_cp_main_t * lcm, vlib_buffer_t * b,
			gid_address_t * rlocs, u8 * locs_put)
{
  u8 *bp, count = 0;
  u32 i;

  bp = vlib_buffer_get_current (b);
  for (i = 0; i < vec_len (rlocs); i++)
    {
      lisp_msg_put_gid (b, &rlocs[i]);
      count++;
    }

  *locs_put = count - 1;
  return bp;
}

void *
lisp_msg_put_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
{
  eid_record_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (*h));

  memset (h, 0, sizeof (*h));
  EID_REC_MLEN (h) = gid_address_len (eid);
  lisp_msg_put_gid (b, eid);
  return h;
}

u64
nonce_build (u32 seed)
{
  u64 nonce;
  u32 nonce_lower;
  u32 nonce_upper;
  struct timespec ts;

  /* Put nanosecond clock in lower 32-bits and put an XOR of the nanosecond
   * clock with the seond clock in the upper 32-bits. */
  syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
  nonce_lower = ts.tv_nsec;
  nonce_upper = ts.tv_sec ^ clib_host_to_net_u32 (nonce_lower);

  /* OR in a caller provided seed to the low-order 32-bits. */
  nonce_lower |= seed;

  /* Return 64-bit nonce. */
  nonce = nonce_upper;
  nonce = (nonce << 32) | nonce_lower;
  return nonce;
}

void *
lisp_msg_put_map_reply (vlib_buffer_t * b, mapping_t * records, u64 nonce,
			u8 probe_bit)
{
  map_reply_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));

  memset (h, 0, sizeof (h[0]));
  MREP_TYPE (h) = LISP_MAP_REPLY;
  MREP_NONCE (h) = nonce;
  MREP_REC_COUNT (h) = 1;
  MREP_RLOC_PROBE (h) = probe_bit;

  lisp_msg_put_mreg_records (b, records);
  return h;
}

void *
lisp_msg_put_map_register (vlib_buffer_t * b, mapping_t * records,
			   u8 want_map_notify, u16 auth_data_len, u64 * nonce,
			   u32 * msg_len)
{
  u8 *auth_data = 0;

  /* Basic header init */
  map_register_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));

  memset (h, 0, sizeof (h[0]));
  MREG_TYPE (h) = LISP_MAP_REGISTER;
  MREG_NONCE (h) = nonce_build (0);
  MREG_WANT_MAP_NOTIFY (h) = want_map_notify ? 1 : 0;
  MREG_REC_COUNT (h) = vec_len (records);

  auth_data = vlib_buffer_put_uninit (b, auth_data_len);
  memset (auth_data, 0, auth_data_len);

  /* Put map register records */
  lisp_msg_put_mreg_records (b, records);

  nonce[0] = MREG_NONCE (h);
  msg_len[0] = vlib_buffer_get_tail (b) - (u8 *) h;
  return h;
}

void *
lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b,
		   gid_address_t * seid, gid_address_t * deid,
		   gid_address_t * rlocs, u8 is_smr_invoked,
		   u8 rloc_probe_set, u64 * nonce)
{
  u8 loc_count = 0;

  /* Basic header init */
  map_request_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));

  memset (h, 0, sizeof (h[0]));
  MREQ_TYPE (h) = LISP_MAP_REQUEST;
  MREQ_NONCE (h) = nonce_build (0);
  MREQ_SMR_INVOKED (h) = is_smr_invoked ? 1 : 0;
  MREQ_RLOC_PROBE (h) = rloc_probe_set ? 1 : 0;

  /* We're adding one eid record */
  increment_record_count (h);

  /* Fill source eid */
  lisp_msg_put_gid (b, seid);

  /* Put itr rlocs */
  lisp_msg_put_itr_rlocs (lcm, b, rlocs, &loc_count);
  MREQ_ITR_RLOC_COUNT (h) = loc_count;

  /* Put eid record */
  lisp_msg_put_eid_rec (b, deid);

  nonce[0] = MREQ_NONCE (h);
  return h;
}

void *
lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t * b, int lp, int rp,
		   gid_address_t * la, gid_address_t * ra)
{
  ecm_hdr_t *h;
  ip_address_t _src_ip, *src_ip = &_src_ip, _dst_ip, *dst_ip = &_dst_ip;
  if (gid_address_type (la) != GID_ADDR_IP_PREFIX)
    {
      /* empty ip4 */
      memset (src_ip, 0, sizeof (src_ip[0]));
      memset (dst_ip, 0, sizeof (dst_ip[0]));
    }
  else
    {
      src_ip = &gid_address_ip (la);
      dst_ip = &gid_address_ip (ra);
    }

  /* Push inner ip and udp */
  pkt_push_udp_and_ip (vm, b, lp, rp, src_ip, dst_ip);

  /* Push lisp ecm hdr */
  h = pkt_push_ecm_hdr (b);

  return h;
}

static u32
msg_type_to_hdr_len (lisp_msg_type_e type)
{
  switch (type)
    {
    case LISP_MAP_REQUEST:
      return (sizeof (map_request_hdr_t));
    case LISP_MAP_REPLY:
      return (sizeof (map_reply_hdr_t));
    default:
      return (0);
    }
}

void *
lisp_msg_pull_hdr (vlib_buffer_t * b, lisp_msg_type_e type)
{
  return vlib_buffer_pull (b, msg_type_to_hdr_len (type));
}

u32
lisp_msg_parse_addr (vlib_buffer_t * b, gid_address_t * eid)
{
  u32 len;
  memset (eid, 0, sizeof (*eid));
  len = gid_address_parse (vlib_buffer_get_current (b), eid);
  if (len != ~0)
    vlib_buffer_pull (b, len);
  return len;
}

u32
lisp_msg_parse_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
{
  eid_record_hdr_t *h = vlib_buffer_get_current (b);
  u32 len;
  memset (eid, 0, sizeof (*eid));
  len = gid_address_parse (EID_REC_ADDR (h), eid);
  if (len == ~0)
    return len;

  gid_address_ippref_len (eid) = EID_REC_MLEN (h);
  vlib_buffer_pull (b, len + sizeof (eid_record_hdr_t));

  return len + sizeof (eid_record_hdr_t);
}

u32
lisp_msg_parse_itr_rlocs (vlib_buffer_t * b, gid_address_t ** rlocs,
			  u8 rloc_count)
{
  gid_address_t tloc;
  u32 i, len = 0, tlen = 0;

  //MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1
  for (i = 0; i < rloc_count; i++)
    {
      len = lisp_msg_parse_addr (b, &tloc);
      if (len == ~0)
	return len;
      vec_add1 (*rlocs, tloc);
      tlen += len;
    }
  return tlen;
}

u32
lisp_msg_parse_loc (vlib_buffer_t * b, locator_t * loc)
{
  int len;

  len = locator_parse (vlib_buffer_get_current (b), loc);
  if (len == ~0)
    return ~0;

  if (!vlib_buffer_has_space (b, sizeof (len)))
    return ~0;
  vlib_buffer_pull (b, len);

  return len;
}

u32
lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
			       locator_t ** locs, locator_t * probed_)
{
  void *h = 0, *loc_hdr = 0;
  locator_t loc, *probed = 0;
  int i = 0, len = 0, llen = 0;

  h = vlib_buffer_get_current (b);
  if (!vlib_buffer_has_space (b, sizeof (mapping_record_hdr_t)))
    return ~0;

  vlib_buffer_pull (b, sizeof (mapping_record_hdr_t));

  memset (eid, 0, sizeof (*eid));
  len = gid_address_parse (vlib_buffer_get_current (b), eid);
  if (len == ~0)
    return len;

  if (!vlib_buffer_has_space (b, sizeof (len)))
    return ~0;

  vlib_buffer_pull (b, len);
  if (GID_ADDR_IP_PREFIX == gid_address_type (eid))
    gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);

  for (i = 0; i < MAP_REC_LOC_COUNT (h); i++)
    {
      loc_hdr = vlib_buffer_get_current (b);

      llen = lisp_msg_parse_loc (b, &loc);
      if (llen == ~0)
	return llen;
      vec_add1 (*locs, loc);
      len += llen;

      if (LOC_PROBED (loc_hdr))
	{
	  if (probed != 0)
	    clib_warning
	      ("Multiple locators probed! Probing only the first!");
	  else
	    probed = &loc;
	}
    }
  /* XXX */
  if (probed_ != 0 && probed)
    *probed_ = *probed;

  return len + sizeof (map_reply_hdr_t);
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */