17b867a8eSJakub Grajciar/*
27b867a8eSJakub Grajciar *------------------------------------------------------------------
37b867a8eSJakub Grajciar * Copyright (c) 2018 Cisco and/or its affiliates.
47b867a8eSJakub Grajciar * Licensed under the Apache License, Version 2.0 (the "License");
57b867a8eSJakub Grajciar * you may not use this file except in compliance with the License.
67b867a8eSJakub Grajciar * You may obtain a copy of the License at:
77b867a8eSJakub Grajciar *
87b867a8eSJakub Grajciar *     http://www.apache.org/licenses/LICENSE-2.0
97b867a8eSJakub Grajciar *
107b867a8eSJakub Grajciar * Unless required by applicable law or agreed to in writing, software
117b867a8eSJakub Grajciar * distributed under the License is distributed on an "AS IS" BASIS,
127b867a8eSJakub Grajciar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137b867a8eSJakub Grajciar * See the License for the specific language governing permissions and
147b867a8eSJakub Grajciar * limitations under the License.
157b867a8eSJakub Grajciar *------------------------------------------------------------------
167b867a8eSJakub Grajciar */
177b867a8eSJakub Grajciar
187b867a8eSJakub Grajciar#include <igmp/igmp.h>
197b867a8eSJakub Grajciar#include <vnet/ip/ip.h>
207b867a8eSJakub Grajciar
217b867a8eSJakub Grajciaru8 *
227b867a8eSJakub Grajciarformat_igmp_type (u8 * s, va_list * args)
237b867a8eSJakub Grajciar{
24947ea622SNeale Ranns  igmp_type_t type = va_arg (*args, int);
257b867a8eSJakub Grajciar
26947ea622SNeale Ranns  switch (type)
27947ea622SNeale Ranns    {
28947ea622SNeale Ranns#define _(n,f) case IGMP_TYPE_##f: return (format (s, "%s", #f));
29947ea622SNeale Ranns      foreach_igmp_type
30947ea622SNeale Ranns#undef _
31947ea622SNeale Ranns    }
32947ea622SNeale Ranns  return format (s, "unknown:%d", type);
337b867a8eSJakub Grajciar}
347b867a8eSJakub Grajciar
357b867a8eSJakub Grajciaru8 *
36947ea622SNeale Rannsformat_igmp_membership_group_type (u8 * s, va_list * args)
377b867a8eSJakub Grajciar{
38947ea622SNeale Ranns  igmp_membership_group_v3_type_t type = va_arg (*args, int);
39947ea622SNeale Ranns
40947ea622SNeale Ranns  switch (type)
41947ea622SNeale Ranns    {
42947ea622SNeale Ranns#define _(n,f)  case IGMP_MEMBERSHIP_GROUP_##f: return (format (s, "%s", #f));
43947ea622SNeale Ranns      foreach_igmp_membership_group_v3_type
44947ea622SNeale Ranns#undef _
45947ea622SNeale Ranns    }
46947ea622SNeale Ranns  return (format (s, "unknown:%d", type));
47947ea622SNeale Ranns}
48947ea622SNeale Ranns
49947ea622SNeale Rannsu8 *
50947ea622SNeale Rannsformat_igmp_filter_mode (u8 * s, va_list * args)
51947ea622SNeale Ranns{
52947ea622SNeale Ranns  igmp_filter_mode_t mode = va_arg (*args, igmp_filter_mode_t);
53947ea622SNeale Ranns
54947ea622SNeale Ranns  switch (mode)
55947ea622SNeale Ranns    {
56947ea622SNeale Ranns#define _(n,f)  case IGMP_FILTER_MODE_##f: return (format (s, "%s", #f));
57947ea622SNeale Ranns      foreach_igmp_filter_mode
58947ea622SNeale Ranns#undef _
59947ea622SNeale Ranns    }
60947ea622SNeale Ranns  return (format (s, "unknown:%d", mode));
617b867a8eSJakub Grajciar
627b867a8eSJakub Grajciar}
637b867a8eSJakub Grajciar
64fe0a2c5aSNeale Rannsu8 *
65fe0a2c5aSNeale Rannsformat_igmp_mode (u8 * s, va_list * args)
66fe0a2c5aSNeale Ranns{
67fe0a2c5aSNeale Ranns  igmp_mode_t mode = va_arg (*args, igmp_mode_t);
68fe0a2c5aSNeale Ranns
69fe0a2c5aSNeale Ranns  switch (mode)
70fe0a2c5aSNeale Ranns    {
71fe0a2c5aSNeale Ranns#define _(n,f)  case IGMP_MODE_##f: return (format (s, "%s", #f));
72fe0a2c5aSNeale Ranns      foreach_igmp_mode
73fe0a2c5aSNeale Ranns#undef _
74fe0a2c5aSNeale Ranns    }
75fe0a2c5aSNeale Ranns  return (format (s, "unknown:%d", mode));
76fe0a2c5aSNeale Ranns
77fe0a2c5aSNeale Ranns}
78fe0a2c5aSNeale Ranns
797b867a8eSJakub Grajciaru8 *
807b867a8eSJakub Grajciarformat_igmp_header (u8 * s, va_list * args)
817b867a8eSJakub Grajciar{
827b867a8eSJakub Grajciar  igmp_header_t *hdr = va_arg (*args, igmp_header_t *);
837b867a8eSJakub Grajciar  u32 max_header_bytes = va_arg (*args, u32);
847b867a8eSJakub Grajciar  u32 indent;
857b867a8eSJakub Grajciar
867b867a8eSJakub Grajciar  if (max_header_bytes < sizeof (hdr[0]))
877b867a8eSJakub Grajciar    return format (s, "IGMP header truncated");
887b867a8eSJakub Grajciar
897b867a8eSJakub Grajciar  indent = format_get_indent (s);
907b867a8eSJakub Grajciar  indent += 2;
917b867a8eSJakub Grajciar
927b867a8eSJakub Grajciar  s =
937b867a8eSJakub Grajciar    format (s, "%U%U: code %u, checksum 0x%04x", format_white_space, indent,
947b867a8eSJakub Grajciar	    format_igmp_type, hdr->type, hdr->code,
957b867a8eSJakub Grajciar	    clib_net_to_host_u16 (hdr->checksum));
967b867a8eSJakub Grajciar  return s;
977b867a8eSJakub Grajciar}
987b867a8eSJakub Grajciar
997b867a8eSJakub Grajciaru8 *
1007b867a8eSJakub Grajciarformat_igmp_report_v3 (u8 * s, va_list * args)
1017b867a8eSJakub Grajciar{
1027b867a8eSJakub Grajciar  igmp_membership_report_v3_t *igmp =
1037b867a8eSJakub Grajciar    va_arg (*args, igmp_membership_report_v3_t *);
1047b867a8eSJakub Grajciar  u32 max_header_bytes = va_arg (*args, u32);
1057b867a8eSJakub Grajciar  igmp_membership_group_v3_t *group;
1067b867a8eSJakub Grajciar
1077b867a8eSJakub Grajciar  u32 len = sizeof (igmp_membership_report_v3_t);
1087b867a8eSJakub Grajciar  u32 indent;
1097b867a8eSJakub Grajciar
1107b867a8eSJakub Grajciar  if (max_header_bytes < sizeof (igmp[0]))
1117b867a8eSJakub Grajciar    return format (s, "IGMP report truncated");
1127b867a8eSJakub Grajciar
1137b867a8eSJakub Grajciar  indent = format_get_indent (s);
1147b867a8eSJakub Grajciar  indent += 2;
1157b867a8eSJakub Grajciar
1167b867a8eSJakub Grajciar  s =
1177b867a8eSJakub Grajciar    format (s, "%Un_groups %u", format_white_space, indent,
1187b867a8eSJakub Grajciar	    clib_net_to_host_u16 (igmp->n_groups));
1197b867a8eSJakub Grajciar  indent += 2;
1207b867a8eSJakub Grajciar  int i, j = 0;
1217b867a8eSJakub Grajciar  for (i = 0; i < clib_net_to_host_u16 (igmp->n_groups); i++)
1227b867a8eSJakub Grajciar    {
1237b867a8eSJakub Grajciar      group = group_ptr (igmp, len);
1247b867a8eSJakub Grajciar      s =
1257b867a8eSJakub Grajciar	format (s, "\n%U%U: %U, sources %u", format_white_space, indent,
126947ea622SNeale Ranns		format_igmp_membership_group_type, group->type,
127947ea622SNeale Ranns		format_ip4_address, &group->group_address,
1287b867a8eSJakub Grajciar		clib_net_to_host_u16 (group->n_src_addresses));
1297b867a8eSJakub Grajciar      indent += 2;
1307b867a8eSJakub Grajciar      for (j = 0; j < clib_net_to_host_u16 (group->n_src_addresses); j++)
1317b867a8eSJakub Grajciar	{
1327b867a8eSJakub Grajciar	  s =
1337b867a8eSJakub Grajciar	    format (s, "\n%U%U", format_white_space, indent,
1347b867a8eSJakub Grajciar		    format_ip4_address, &group->src_addresses[j]);
1357b867a8eSJakub Grajciar	}
1367b867a8eSJakub Grajciar      indent -= 2;
1377b867a8eSJakub Grajciar      len +=
1387b867a8eSJakub Grajciar	sizeof (igmp_membership_group_v3_t) +
1397b867a8eSJakub Grajciar	(sizeof (ip4_address_t) *
1407b867a8eSJakub Grajciar	 clib_net_to_host_u16 (group->n_src_addresses));
1417b867a8eSJakub Grajciar    }
1427b867a8eSJakub Grajciar  return s;
1437b867a8eSJakub Grajciar}
1447b867a8eSJakub Grajciar
1457b867a8eSJakub Grajciaru8 *
1467b867a8eSJakub Grajciarformat_igmp_query_v3 (u8 * s, va_list * args)
1477b867a8eSJakub Grajciar{
1487b867a8eSJakub Grajciar  igmp_membership_query_v3_t *igmp =
1497b867a8eSJakub Grajciar    va_arg (*args, igmp_membership_query_v3_t *);
1507b867a8eSJakub Grajciar  u32 max_header_bytes = va_arg (*args, u32);
1517b867a8eSJakub Grajciar  u32 indent;
1527b867a8eSJakub Grajciar  int i;
1537b867a8eSJakub Grajciar
1547b867a8eSJakub Grajciar  if (max_header_bytes < sizeof (igmp[0]))
1557b867a8eSJakub Grajciar    return format (s, "IGMP query truncated");
1567b867a8eSJakub Grajciar
1577b867a8eSJakub Grajciar  indent = format_get_indent (s);
1587b867a8eSJakub Grajciar  indent += 2;
1597b867a8eSJakub Grajciar
1607b867a8eSJakub Grajciar  ip4_address_t tmp;
1617b867a8eSJakub Grajciar  tmp.as_u32 = 0;
1627b867a8eSJakub Grajciar
163947ea622SNeale Ranns  if ((!ip4_address_compare (&igmp->group_address, &tmp))
1647b867a8eSJakub Grajciar      && (igmp->n_src_addresses == 0))
1657b867a8eSJakub Grajciar    s = format (s, "%UGeneral Query", format_white_space, indent);
1667b867a8eSJakub Grajciar  else if (igmp->n_src_addresses == 0)
1677b867a8eSJakub Grajciar    s = format (s, "%UGroup-Specific Query: %U", format_white_space, indent,
168947ea622SNeale Ranns		format_ip4_address, &igmp->group_address);
1697b867a8eSJakub Grajciar  else
1707b867a8eSJakub Grajciar    {
1717b867a8eSJakub Grajciar      s =
1727b867a8eSJakub Grajciar	format (s, "%UGroup-and-Source-Specific Query: %U",
173947ea622SNeale Ranns		format_white_space, indent, format_ip4_address,
174947ea622SNeale Ranns		&igmp->group_address);
1757b867a8eSJakub Grajciar      indent += 2;
1767b867a8eSJakub Grajciar      for (i = 0; i < clib_net_to_host_u16 (igmp->n_src_addresses); i++)
1777b867a8eSJakub Grajciar	{
1787b867a8eSJakub Grajciar	  s = format (s, "\n%U%U", format_white_space, indent,
1797b867a8eSJakub Grajciar		      format_ip4_address, &igmp->src_addresses[i]);
1807b867a8eSJakub Grajciar	}
1817b867a8eSJakub Grajciar    }
1827b867a8eSJakub Grajciar  return s;
1837b867a8eSJakub Grajciar}
1847b867a8eSJakub Grajciar
185947ea622SNeale Rannsu8 *
186947ea622SNeale Rannsformat_igmp_src_addr_list (u8 * s, va_list * args)
187947ea622SNeale Ranns{
188947ea622SNeale Ranns  ip46_address_t *ss, *srcs;
189947ea622SNeale Ranns
190947ea622SNeale Ranns  srcs = va_arg (*args, ip46_address_t *);
191947ea622SNeale Ranns
192947ea622SNeale Ranns  s = format (s, "[");
193947ea622SNeale Ranns  vec_foreach (ss, srcs)
194947ea622SNeale Ranns  {
195947ea622SNeale Ranns    s = format (s, "%U ", format_ip46_address, ss, IP46_TYPE_ANY);
196947ea622SNeale Ranns  }
197947ea622SNeale Ranns  s = format (s, "]");
198947ea622SNeale Ranns
199947ea622SNeale Ranns  return (s);
200947ea622SNeale Ranns}
201947ea622SNeale Ranns
202947ea622SNeale Rannsu8 *
203947ea622SNeale Rannsformat_igmp_key (u8 * s, va_list * args)
204947ea622SNeale Ranns{
205947ea622SNeale Ranns  const igmp_key_t *key = va_arg (*args, const igmp_key_t *);
206947ea622SNeale Ranns
207947ea622SNeale Ranns  s = format (s, "%U", format_ip46_address, key, IP46_TYPE_ANY);
208947ea622SNeale Ranns
209947ea622SNeale Ranns  return (s);
210947ea622SNeale Ranns}
211947ea622SNeale Ranns
21297748caeSJakub Grajciaru8 *
21397748caeSJakub Grajciarformat_igmp_proxy_device_id (u8 * s, va_list * args)
21497748caeSJakub Grajciar{
21597748caeSJakub Grajciar  u32 id = va_arg (*args, u32);
21697748caeSJakub Grajciar
21797748caeSJakub Grajciar  s = (id == ~0) ? s : format (s, "proxy device: %u", id);
21897748caeSJakub Grajciar
21997748caeSJakub Grajciar  return (s);
22097748caeSJakub Grajciar}
22197748caeSJakub Grajciar
2227b867a8eSJakub Grajciar/*
2237b867a8eSJakub Grajciar * fd.io coding-style-patch-verification: ON
2247b867a8eSJakub Grajciar *
2257b867a8eSJakub Grajciar * Local Variables:
2267b867a8eSJakub Grajciar * eval: (c-set-style "gnu")
2277b867a8eSJakub Grajciar * End:
2287b867a8eSJakub Grajciar */