diff options
| author | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:03:14 +0200 | 
|---|---|---|
| committer | whitespace / reindent <invalid@invalid.invalid> | 2017-07-17 14:04:07 +0200 | 
| commit | d62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch) | |
| tree | 3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /pimd | |
| parent | 888ac268a0077fc9ebd1218cec6ae472af0bfc40 (diff) | |
*: reindentreindent-master-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'pimd')
81 files changed, 25935 insertions, 25405 deletions
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 37515cee59..f68c252a35 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -42,283 +42,280 @@ static void assert_action_a2(struct pim_ifchannel *ch,  static void assert_action_a6(struct pim_ifchannel *ch,  			     struct pim_assert_metric winner_metric); -void pim_ifassert_winner_set(struct pim_ifchannel     *ch, -			     enum pim_ifassert_state   new_state, -			     struct in_addr            winner, -			     struct pim_assert_metric  winner_metric) +void pim_ifassert_winner_set(struct pim_ifchannel *ch, +			     enum pim_ifassert_state new_state, +			     struct in_addr winner, +			     struct pim_assert_metric winner_metric)  { -  int winner_changed = (ch->ifassert_winner.s_addr != winner.s_addr); -  int metric_changed = !pim_assert_metric_match(&ch->ifassert_winner_metric, -						&winner_metric); - -  if (PIM_DEBUG_PIM_EVENTS) { -    if (ch->ifassert_state != new_state) { -      zlog_debug("%s: (S,G)=%s assert state changed from %s to %s on interface %s", -		 __PRETTY_FUNCTION__, -		 ch->sg_str, -		 pim_ifchannel_ifassert_name(ch->ifassert_state), -		 pim_ifchannel_ifassert_name(new_state), -		 ch->interface->name); -    } - -    if (winner_changed) { -      char was_str[INET_ADDRSTRLEN]; -      char winner_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<was?>", ch->ifassert_winner, was_str, sizeof(was_str)); -      pim_inet4_dump("<winner?>", winner, winner_str, sizeof(winner_str)); -      zlog_debug("%s: (S,G)=%s assert winner changed from %s to %s on interface %s", -		 __PRETTY_FUNCTION__, -		 ch->sg_str, -		 was_str, winner_str, ch->interface->name); -    } -  } /* PIM_DEBUG_PIM_EVENTS */ - -  ch->ifassert_state         = new_state; -  ch->ifassert_winner        = winner; -  ch->ifassert_winner_metric = winner_metric; -  ch->ifassert_creation      = pim_time_monotonic_sec(); - -  if (winner_changed || metric_changed) { -    pim_upstream_update_join_desired(ch->upstream); -    pim_ifchannel_update_could_assert(ch); -    pim_ifchannel_update_assert_tracking_desired(ch); -  } +	int winner_changed = (ch->ifassert_winner.s_addr != winner.s_addr); +	int metric_changed = !pim_assert_metric_match( +		&ch->ifassert_winner_metric, &winner_metric); + +	if (PIM_DEBUG_PIM_EVENTS) { +		if (ch->ifassert_state != new_state) { +			zlog_debug( +				"%s: (S,G)=%s assert state changed from %s to %s on interface %s", +				__PRETTY_FUNCTION__, ch->sg_str, +				pim_ifchannel_ifassert_name(ch->ifassert_state), +				pim_ifchannel_ifassert_name(new_state), +				ch->interface->name); +		} + +		if (winner_changed) { +			char was_str[INET_ADDRSTRLEN]; +			char winner_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<was?>", ch->ifassert_winner, was_str, +				       sizeof(was_str)); +			pim_inet4_dump("<winner?>", winner, winner_str, +				       sizeof(winner_str)); +			zlog_debug( +				"%s: (S,G)=%s assert winner changed from %s to %s on interface %s", +				__PRETTY_FUNCTION__, ch->sg_str, was_str, +				winner_str, ch->interface->name); +		} +	} /* PIM_DEBUG_PIM_EVENTS */ + +	ch->ifassert_state = new_state; +	ch->ifassert_winner = winner; +	ch->ifassert_winner_metric = winner_metric; +	ch->ifassert_creation = pim_time_monotonic_sec(); + +	if (winner_changed || metric_changed) { +		pim_upstream_update_join_desired(ch->upstream); +		pim_ifchannel_update_could_assert(ch); +		pim_ifchannel_update_assert_tracking_desired(ch); +	}  } -static void on_trace(const char *label, -		     struct interface *ifp, struct in_addr src) +static void on_trace(const char *label, struct interface *ifp, +		     struct in_addr src)  { -  if (PIM_DEBUG_PIM_TRACE) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); -    zlog_debug("%s: from %s on %s", -	       label, src_str, ifp->name); -  } +	if (PIM_DEBUG_PIM_TRACE) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); +		zlog_debug("%s: from %s on %s", label, src_str, ifp->name); +	}  }  static int preferred_assert(const struct pim_ifchannel *ch,  			    const struct pim_assert_metric *recv_metric)  { -  return pim_assert_metric_better(recv_metric, -				  &ch->ifassert_winner_metric); +	return pim_assert_metric_better(recv_metric, +					&ch->ifassert_winner_metric);  }  static int acceptable_assert(const struct pim_assert_metric *my_metric,  			     const struct pim_assert_metric *recv_metric)  { -  return pim_assert_metric_better(recv_metric, -				  my_metric); +	return pim_assert_metric_better(recv_metric, my_metric);  }  static int inferior_assert(const struct pim_assert_metric *my_metric,  			   const struct pim_assert_metric *recv_metric)  { -  return pim_assert_metric_better(my_metric, -				  recv_metric); +	return pim_assert_metric_better(my_metric, recv_metric);  }  static int cancel_assert(const struct pim_assert_metric *recv_metric)  { -  return (recv_metric->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) -    && -    (recv_metric->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX); +	return (recv_metric->metric_preference +		== PIM_ASSERT_METRIC_PREFERENCE_MAX) +	       && (recv_metric->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX);  } -static void if_could_assert_do_a1(const char *caller, -				  struct pim_ifchannel *ch) +static void if_could_assert_do_a1(const char *caller, struct pim_ifchannel *ch)  { -  if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { -    if (assert_action_a1(ch)) { -      zlog_warn("%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", -		__PRETTY_FUNCTION__, caller, -		ch->sg_str, ch->interface->name); -      /* log warning only */ -    } -  } +	if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { +		if (assert_action_a1(ch)) { +			zlog_warn( +				"%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", +				__PRETTY_FUNCTION__, caller, ch->sg_str, +				ch->interface->name); +			/* log warning only */ +		} +	}  } -static int dispatch_assert(struct interface *ifp, -			   struct in_addr source_addr, +static int dispatch_assert(struct interface *ifp, struct in_addr source_addr,  			   struct in_addr group_addr,  			   struct pim_assert_metric recv_metric)  { -  struct pim_ifchannel *ch; -  struct prefix_sg sg; - -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = source_addr; -  sg.grp = group_addr; -  ch = pim_ifchannel_add(ifp, &sg, 0); -  if (!ch) { -    zlog_warn("%s: (S,G)=%s failure creating channel on interface %s", -	      __PRETTY_FUNCTION__, -	      pim_str_sg_dump (&sg), ifp->name); -    return -1; -  } - -  switch (ch->ifassert_state) { -  case PIM_IFASSERT_NOINFO: -    if (recv_metric.rpt_bit_flag) { -      /* RPT bit set */ -      if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); -    } -    else { -      /* RPT bit clear */ -      if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { -	if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); -      } -      else if (acceptable_assert(&ch->ifassert_my_metric, &recv_metric)) { -	if (PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)) { -	  assert_action_a6(ch, recv_metric); -	} -      } -    } -    break; -  case PIM_IFASSERT_I_AM_WINNER: -    if (preferred_assert(ch, &recv_metric)) { -      assert_action_a2(ch, recv_metric); -    } -    else { -      if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { -	assert_action_a3(ch); -      } -    } -    break; -  case PIM_IFASSERT_I_AM_LOSER: -    if (recv_metric.ip_address.s_addr == ch->ifassert_winner.s_addr) { -      /* Assert from current winner */ - -      if (cancel_assert(&recv_metric)) { -	assert_action_a5(ch); -      } -      else { -	if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { -	  assert_action_a5(ch); -	} -	else if (acceptable_assert(&ch->ifassert_my_metric, &recv_metric)) { -	  if (!recv_metric.rpt_bit_flag) { -	    assert_action_a2(ch, recv_metric); -	  } -	} -      } -    } -    else if (preferred_assert(ch, &recv_metric)) { -      assert_action_a2(ch, recv_metric); -    } -    break; -  default: -    { -      zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", -		__PRETTY_FUNCTION__, -		ch->sg_str, ch->ifassert_state, ifp->name); -    } -    return -2; -  } - -  return 0; +	struct pim_ifchannel *ch; +	struct prefix_sg sg; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = source_addr; +	sg.grp = group_addr; +	ch = pim_ifchannel_add(ifp, &sg, 0); +	if (!ch) { +		zlog_warn( +			"%s: (S,G)=%s failure creating channel on interface %s", +			__PRETTY_FUNCTION__, pim_str_sg_dump(&sg), ifp->name); +		return -1; +	} + +	switch (ch->ifassert_state) { +	case PIM_IFASSERT_NOINFO: +		if (recv_metric.rpt_bit_flag) { +			/* RPT bit set */ +			if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); +		} else { +			/* RPT bit clear */ +			if (inferior_assert(&ch->ifassert_my_metric, +					    &recv_metric)) { +				if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); +			} else if (acceptable_assert(&ch->ifassert_my_metric, +						     &recv_metric)) { +				if (PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED( +					    ch->flags)) { +					assert_action_a6(ch, recv_metric); +				} +			} +		} +		break; +	case PIM_IFASSERT_I_AM_WINNER: +		if (preferred_assert(ch, &recv_metric)) { +			assert_action_a2(ch, recv_metric); +		} else { +			if (inferior_assert(&ch->ifassert_my_metric, +					    &recv_metric)) { +				assert_action_a3(ch); +			} +		} +		break; +	case PIM_IFASSERT_I_AM_LOSER: +		if (recv_metric.ip_address.s_addr +		    == ch->ifassert_winner.s_addr) { +			/* Assert from current winner */ + +			if (cancel_assert(&recv_metric)) { +				assert_action_a5(ch); +			} else { +				if (inferior_assert(&ch->ifassert_my_metric, +						    &recv_metric)) { +					assert_action_a5(ch); +				} else if (acceptable_assert( +						   &ch->ifassert_my_metric, +						   &recv_metric)) { +					if (!recv_metric.rpt_bit_flag) { +						assert_action_a2(ch, +								 recv_metric); +					} +				} +			} +		} else if (preferred_assert(ch, &recv_metric)) { +			assert_action_a2(ch, recv_metric); +		} +		break; +	default: { +		zlog_warn( +			"%s: (S,G)=%s invalid assert state %d on interface %s", +			__PRETTY_FUNCTION__, ch->sg_str, ch->ifassert_state, +			ifp->name); +	} +		return -2; +	} + +	return 0;  } -int pim_assert_recv(struct interface *ifp, -		    struct pim_neighbor *neigh, -		    struct in_addr src_addr, -		    uint8_t *buf, int buf_size) +int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, +		    struct in_addr src_addr, uint8_t *buf, int buf_size)  { -  struct prefix_sg         sg; -  struct prefix            msg_source_addr; -  struct pim_assert_metric msg_metric; -  int offset; -  uint8_t *curr; -  int curr_size; -  struct pim_interface *pim_ifp = NULL; - -  on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - -  curr      = buf; -  curr_size = buf_size; - -  /* -    Parse assert group addr -   */ -  memset (&sg, 0, sizeof (struct prefix_sg)); -  offset = pim_parse_addr_group (&sg, curr, curr_size); -  if (offset < 1) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s", -	      __PRETTY_FUNCTION__, -	      src_str, ifp->name); -    return -1; -  } -  curr      += offset; -  curr_size -= offset; - -  /* -    Parse assert source addr -  */ -  offset = pim_parse_addr_ucast (&msg_source_addr, curr, curr_size); -  if (offset < 1) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", -	      __PRETTY_FUNCTION__, -	      src_str, ifp->name); -    return -2; -  } -  curr      += offset; -  curr_size -= offset; - -  if (curr_size != 8) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: preference/metric size is not 8: size=%d from %s on interface %s", -	      __PRETTY_FUNCTION__, -	      curr_size, -	      src_str, ifp->name); -    return -3; -  } - -  /* -    Parse assert metric preference -  */ - -  msg_metric.metric_preference = pim_read_uint32_host(curr); - -  msg_metric.rpt_bit_flag = msg_metric.metric_preference & 0x80000000; /* save highest bit */ -  msg_metric.metric_preference &= ~0x80000000; /* clear highest bit */ - -  curr += 4; - -  /* -    Parse assert route metric -  */ - -  msg_metric.route_metric = pim_read_uint32_host(curr); - -  if (PIM_DEBUG_PIM_TRACE) { -    char neigh_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<neigh?>", src_addr, neigh_str, sizeof(neigh_str)); -    pim_inet4_dump("<src?>", msg_source_addr.u.prefix4, source_str, sizeof(source_str)); -    pim_inet4_dump("<grp?>", sg.grp, group_str, sizeof(group_str)); -    zlog_debug("%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", -	       __PRETTY_FUNCTION__, neigh_str, ifp->name, -	       source_str, group_str, -	       msg_metric.metric_preference, -	       msg_metric.route_metric, -	       PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag)); -  } - -  msg_metric.ip_address = src_addr; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); -  ++pim_ifp->pim_ifstat_assert_recv; - -  return dispatch_assert(ifp, -			 msg_source_addr.u.prefix4, -			 sg.grp, -			 msg_metric); +	struct prefix_sg sg; +	struct prefix msg_source_addr; +	struct pim_assert_metric msg_metric; +	int offset; +	uint8_t *curr; +	int curr_size; +	struct pim_interface *pim_ifp = NULL; + +	on_trace(__PRETTY_FUNCTION__, ifp, src_addr); + +	curr = buf; +	curr_size = buf_size; + +	/* +	  Parse assert group addr +	 */ +	memset(&sg, 0, sizeof(struct prefix_sg)); +	offset = pim_parse_addr_group(&sg, curr, curr_size); +	if (offset < 1) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s", +			  __PRETTY_FUNCTION__, src_str, ifp->name); +		return -1; +	} +	curr += offset; +	curr_size -= offset; + +	/* +	  Parse assert source addr +	*/ +	offset = pim_parse_addr_ucast(&msg_source_addr, curr, curr_size); +	if (offset < 1) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", +			  __PRETTY_FUNCTION__, src_str, ifp->name); +		return -2; +	} +	curr += offset; +	curr_size -= offset; + +	if (curr_size != 8) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn( +			"%s: preference/metric size is not 8: size=%d from %s on interface %s", +			__PRETTY_FUNCTION__, curr_size, src_str, ifp->name); +		return -3; +	} + +	/* +	  Parse assert metric preference +	*/ + +	msg_metric.metric_preference = pim_read_uint32_host(curr); + +	msg_metric.rpt_bit_flag = msg_metric.metric_preference +				  & 0x80000000;      /* save highest bit */ +	msg_metric.metric_preference &= ~0x80000000; /* clear highest bit */ + +	curr += 4; + +	/* +	  Parse assert route metric +	*/ + +	msg_metric.route_metric = pim_read_uint32_host(curr); + +	if (PIM_DEBUG_PIM_TRACE) { +		char neigh_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<neigh?>", src_addr, neigh_str, +			       sizeof(neigh_str)); +		pim_inet4_dump("<src?>", msg_source_addr.u.prefix4, source_str, +			       sizeof(source_str)); +		pim_inet4_dump("<grp?>", sg.grp, group_str, sizeof(group_str)); +		zlog_debug( +			"%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", +			__PRETTY_FUNCTION__, neigh_str, ifp->name, source_str, +			group_str, msg_metric.metric_preference, +			msg_metric.route_metric, +			PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag)); +	} + +	msg_metric.ip_address = src_addr; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); +	++pim_ifp->pim_ifstat_assert_recv; + +	return dispatch_assert(ifp, msg_source_addr.u.prefix4, sg.grp, +			       msg_metric);  }  /* @@ -335,167 +332,164 @@ int pim_assert_recv(struct interface *ifp,  int pim_assert_metric_better(const struct pim_assert_metric *m1,  			     const struct pim_assert_metric *m2)  { -  if (m1->rpt_bit_flag < m2->rpt_bit_flag) -    return 1; -  if (m1->rpt_bit_flag > m2->rpt_bit_flag) -    return 0; - -  if (m1->metric_preference < m2->metric_preference) -    return 1; -  if (m1->metric_preference > m2->metric_preference) -    return 0; - -  if (m1->route_metric < m2->route_metric) -    return 1; -  if (m1->route_metric > m2->route_metric) -    return 0; - -  return ntohl(m1->ip_address.s_addr) > ntohl(m2->ip_address.s_addr); +	if (m1->rpt_bit_flag < m2->rpt_bit_flag) +		return 1; +	if (m1->rpt_bit_flag > m2->rpt_bit_flag) +		return 0; + +	if (m1->metric_preference < m2->metric_preference) +		return 1; +	if (m1->metric_preference > m2->metric_preference) +		return 0; + +	if (m1->route_metric < m2->route_metric) +		return 1; +	if (m1->route_metric > m2->route_metric) +		return 0; + +	return ntohl(m1->ip_address.s_addr) > ntohl(m2->ip_address.s_addr);  }  int pim_assert_metric_match(const struct pim_assert_metric *m1,  			    const struct pim_assert_metric *m2)  { -  if (m1->rpt_bit_flag != m2->rpt_bit_flag) -    return 0; -  if (m1->metric_preference != m2->metric_preference) -    return 0; -  if (m1->route_metric != m2->route_metric) -    return 0; -   -  return m1->ip_address.s_addr == m2->ip_address.s_addr; +	if (m1->rpt_bit_flag != m2->rpt_bit_flag) +		return 0; +	if (m1->metric_preference != m2->metric_preference) +		return 0; +	if (m1->route_metric != m2->route_metric) +		return 0; + +	return m1->ip_address.s_addr == m2->ip_address.s_addr;  } -int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, -			 struct interface *ifp, -			 struct in_addr group_addr, -			 struct in_addr source_addr, -			 uint32_t metric_preference, -			 uint32_t route_metric, +int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp, +			 struct in_addr group_addr, struct in_addr source_addr, +			 uint32_t metric_preference, uint32_t route_metric,  			 uint32_t rpt_bit_flag)  { -  uint8_t *buf_pastend = pim_msg + buf_size; -  uint8_t *pim_msg_curr; -  int pim_msg_size; -  int remain; - -  pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; /* skip room for pim header */ - -  /* Encode group */ -  remain = buf_pastend - pim_msg_curr; -  pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr); -  if (!pim_msg_curr) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    zlog_warn("%s: failure encoding group address %s: space left=%d", -	      __PRETTY_FUNCTION__, group_str, remain); -    return -1; -  } - -  /* Encode source */ -  remain = buf_pastend - pim_msg_curr; -  pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr); -  if (!pim_msg_curr) { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: failure encoding source address %s: space left=%d", -	      __PRETTY_FUNCTION__, source_str, remain); -    return -2; -  } - -  /* Metric preference */ -  pim_write_uint32(pim_msg_curr, rpt_bit_flag ? -		   metric_preference | 0x80000000 : -		   metric_preference); -  pim_msg_curr += 4; - -  /* Route metric */ -  pim_write_uint32(pim_msg_curr, route_metric); -  pim_msg_curr += 4; - -  /* -    Add PIM header -  */ -  pim_msg_size = pim_msg_curr - pim_msg; -  pim_msg_build_header(pim_msg, pim_msg_size, -		       PIM_MSG_TYPE_ASSERT); - -  return pim_msg_size; +	uint8_t *buf_pastend = pim_msg + buf_size; +	uint8_t *pim_msg_curr; +	int pim_msg_size; +	int remain; + +	pim_msg_curr = +		pim_msg + PIM_MSG_HEADER_LEN; /* skip room for pim header */ + +	/* Encode group */ +	remain = buf_pastend - pim_msg_curr; +	pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr); +	if (!pim_msg_curr) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		zlog_warn( +			"%s: failure encoding group address %s: space left=%d", +			__PRETTY_FUNCTION__, group_str, remain); +		return -1; +	} + +	/* Encode source */ +	remain = buf_pastend - pim_msg_curr; +	pim_msg_curr = +		pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr); +	if (!pim_msg_curr) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: failure encoding source address %s: space left=%d", +			__PRETTY_FUNCTION__, source_str, remain); +		return -2; +	} + +	/* Metric preference */ +	pim_write_uint32(pim_msg_curr, +			 rpt_bit_flag ? metric_preference | 0x80000000 +				      : metric_preference); +	pim_msg_curr += 4; + +	/* Route metric */ +	pim_write_uint32(pim_msg_curr, route_metric); +	pim_msg_curr += 4; + +	/* +	  Add PIM header +	*/ +	pim_msg_size = pim_msg_curr - pim_msg; +	pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_ASSERT); + +	return pim_msg_size;  }  static int pim_assert_do(struct pim_ifchannel *ch,  			 struct pim_assert_metric metric)  { -  struct interface *ifp; -  struct pim_interface *pim_ifp; -  uint8_t pim_msg[1000]; -  int pim_msg_size; - -  ifp = ch->interface; -  if (!ifp) -    { -      if (PIM_DEBUG_PIM_TRACE) -	zlog_debug("%s: channel%s has no associated interface!", -		   __PRETTY_FUNCTION__, ch->sg_str); -      return -1; -    } -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    if (PIM_DEBUG_PIM_TRACE) -      zlog_debug("%s: channel %s pim not enabled on interface: %s", -		 __PRETTY_FUNCTION__, ch->sg_str, ifp->name); -    return -1; -  } - -  pim_msg_size = pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, -				      ch->sg.grp, ch->sg.src, -				      metric.metric_preference, -				      metric.route_metric, -				      metric.rpt_bit_flag); -  if (pim_msg_size < 1) { -    zlog_warn("%s: failure building PIM assert message: msg_size=%d", -	      __PRETTY_FUNCTION__, pim_msg_size); -    return -2; -  } - -  /* -    RFC 4601: 4.3.1.  Sending Hello Messages -     -    Thus, if a router needs to send a Join/Prune or Assert message on -    an interface on which it has not yet sent a Hello message with the -    currently configured IP address, then it MUST immediately send the -    relevant Hello message without waiting for the Hello Timer to -    expire, followed by the Join/Prune or Assert message. -  */ -  pim_hello_require(ifp); - -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", -	       __PRETTY_FUNCTION__,  -	       ifp->name, ch->sg_str, -	       metric.metric_preference, -	       metric.route_metric, -	       PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); -  } -  ++pim_ifp->pim_ifstat_assert_send; - -  if (pim_msg_send(pim_ifp->pim_sock_fd, -		   pim_ifp->primary_address, -		   qpim_all_pim_routers_addr, -		   pim_msg, -		   pim_msg_size, -		   ifp->name)) { -    zlog_warn("%s: could not send PIM message on interface %s", -	      __PRETTY_FUNCTION__, ifp->name); -    return -3; -  } - -  return 0; +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	uint8_t pim_msg[1000]; +	int pim_msg_size; + +	ifp = ch->interface; +	if (!ifp) { +		if (PIM_DEBUG_PIM_TRACE) +			zlog_debug("%s: channel%s has no associated interface!", +				   __PRETTY_FUNCTION__, ch->sg_str); +		return -1; +	} +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		if (PIM_DEBUG_PIM_TRACE) +			zlog_debug( +				"%s: channel %s pim not enabled on interface: %s", +				__PRETTY_FUNCTION__, ch->sg_str, ifp->name); +		return -1; +	} + +	pim_msg_size = +		pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, ch->sg.grp, +				     ch->sg.src, metric.metric_preference, +				     metric.route_metric, metric.rpt_bit_flag); +	if (pim_msg_size < 1) { +		zlog_warn( +			"%s: failure building PIM assert message: msg_size=%d", +			__PRETTY_FUNCTION__, pim_msg_size); +		return -2; +	} + +	/* +	  RFC 4601: 4.3.1.  Sending Hello Messages + +	  Thus, if a router needs to send a Join/Prune or Assert message on +	  an interface on which it has not yet sent a Hello message with the +	  currently configured IP address, then it MUST immediately send the +	  relevant Hello message without waiting for the Hello Timer to +	  expire, followed by the Join/Prune or Assert message. +	*/ +	pim_hello_require(ifp); + +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", +			   __PRETTY_FUNCTION__, ifp->name, ch->sg_str, +			   metric.metric_preference, metric.route_metric, +			   PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); +	} +	++pim_ifp->pim_ifstat_assert_send; + +	if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, +			 qpim_all_pim_routers_addr, pim_msg, pim_msg_size, +			 ifp->name)) { +		zlog_warn("%s: could not send PIM message on interface %s", +			  __PRETTY_FUNCTION__, ifp->name); +		return -3; +	} + +	return 0;  }  int pim_assert_send(struct pim_ifchannel *ch)  { -  return pim_assert_do(ch, ch->ifassert_my_metric); +	return pim_assert_do(ch, ch->ifassert_my_metric);  }  /* @@ -506,82 +500,82 @@ int pim_assert_send(struct pim_ifchannel *ch)   */  static int pim_assert_cancel(struct pim_ifchannel *ch)  { -  struct pim_assert_metric metric; +	struct pim_assert_metric metric; -  metric.rpt_bit_flag      = 0; -  metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; -  metric.route_metric      = PIM_ASSERT_ROUTE_METRIC_MAX; -  metric.ip_address        = ch->sg.src; +	metric.rpt_bit_flag = 0; +	metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; +	metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; +	metric.ip_address = ch->sg.src; -  return pim_assert_do(ch, metric); +	return pim_assert_do(ch, metric);  }  static int on_assert_timer(struct thread *t)  { -  struct pim_ifchannel *ch; -  struct interface *ifp; - -  ch = THREAD_ARG(t); - -  ifp = ch->interface; - -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("%s: (S,G)=%s timer expired on interface %s", -	       __PRETTY_FUNCTION__, -	       ch->sg_str, ifp->name); -  } - -  ch->t_ifassert_timer = NULL; - -  switch (ch->ifassert_state) { -  case PIM_IFASSERT_I_AM_WINNER: -    assert_action_a3(ch); -    break; -  case PIM_IFASSERT_I_AM_LOSER: -    assert_action_a5(ch); -    break; -  default: -    { -      if (PIM_DEBUG_PIM_EVENTS) -	zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", -		  __PRETTY_FUNCTION__, -		  ch->sg_str, ch->ifassert_state, ifp->name); -    } -  } - -  return 0; +	struct pim_ifchannel *ch; +	struct interface *ifp; + +	ch = THREAD_ARG(t); + +	ifp = ch->interface; + +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("%s: (S,G)=%s timer expired on interface %s", +			   __PRETTY_FUNCTION__, ch->sg_str, ifp->name); +	} + +	ch->t_ifassert_timer = NULL; + +	switch (ch->ifassert_state) { +	case PIM_IFASSERT_I_AM_WINNER: +		assert_action_a3(ch); +		break; +	case PIM_IFASSERT_I_AM_LOSER: +		assert_action_a5(ch); +		break; +	default: { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_warn( +				"%s: (S,G)=%s invalid assert state %d on interface %s", +				__PRETTY_FUNCTION__, ch->sg_str, +				ch->ifassert_state, ifp->name); +	} +	} + +	return 0;  }  static void assert_timer_off(struct pim_ifchannel *ch)  { -  if (PIM_DEBUG_PIM_TRACE) { -    if (ch->t_ifassert_timer) { -      zlog_debug("%s: (S,G)=%s cancelling timer on interface %s", -		 __PRETTY_FUNCTION__, -		 ch->sg_str, ch->interface->name); -    } -  } -  THREAD_OFF(ch->t_ifassert_timer); +	if (PIM_DEBUG_PIM_TRACE) { +		if (ch->t_ifassert_timer) { +			zlog_debug( +				"%s: (S,G)=%s cancelling timer on interface %s", +				__PRETTY_FUNCTION__, ch->sg_str, +				ch->interface->name); +		} +	} +	THREAD_OFF(ch->t_ifassert_timer);  } -static void pim_assert_timer_set(struct pim_ifchannel *ch, -				 int interval) +static void pim_assert_timer_set(struct pim_ifchannel *ch, int interval)  { -  assert_timer_off(ch); +	assert_timer_off(ch); -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", -	       __PRETTY_FUNCTION__, -	       ch->sg_str, interval, ch->interface->name); -  } +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", +			   __PRETTY_FUNCTION__, ch->sg_str, interval, +			   ch->interface->name); +	} -  thread_add_timer(master, on_assert_timer, ch, interval, -                   &ch->t_ifassert_timer); +	thread_add_timer(master, on_assert_timer, ch, interval, +			 &ch->t_ifassert_timer);  }  static void pim_assert_timer_reset(struct pim_ifchannel *ch)  { -  pim_assert_timer_set(ch, PIM_ASSERT_TIME - PIM_ASSERT_OVERRIDE_INTERVAL); +	pim_assert_timer_set(ch, +			     PIM_ASSERT_TIME - PIM_ASSERT_OVERRIDE_INTERVAL);  }  /* @@ -596,38 +590,37 @@ static void pim_assert_timer_reset(struct pim_ifchannel *ch)  */  int assert_action_a1(struct pim_ifchannel *ch)  { -  struct interface *ifp = ch->interface; -  struct pim_interface *pim_ifp; - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__, -	      ch->sg_str, ifp->name); -    return -1; /* must return since pim_ifp is used below */ -  } - -  /* Switch to I_AM_WINNER before performing action_a3 below */ -  pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_WINNER, -			  pim_ifp->primary_address, -			  pim_macro_spt_assert_metric(&ch->upstream->rpf, -						      pim_ifp->primary_address)); - -  if (assert_action_a3(ch)) { -    zlog_warn("%s: (S,G)=%s assert_action_a3 failure on interface %s", -	      __PRETTY_FUNCTION__, -	      ch->sg_str, ifp->name); -    /* warning only */ -  } - -  if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) -    { -      if (PIM_DEBUG_PIM_EVENTS) -	zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_WINNER state", -		  __PRETTY_FUNCTION__, ch->sg_str); -    } - -  return 0; +	struct interface *ifp = ch->interface; +	struct pim_interface *pim_ifp; + +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ch->sg_str, ifp->name); +		return -1; /* must return since pim_ifp is used below */ +	} + +	/* Switch to I_AM_WINNER before performing action_a3 below */ +	pim_ifassert_winner_set( +		ch, PIM_IFASSERT_I_AM_WINNER, pim_ifp->primary_address, +		pim_macro_spt_assert_metric(&ch->upstream->rpf, +					    pim_ifp->primary_address)); + +	if (assert_action_a3(ch)) { +		zlog_warn( +			"%s: (S,G)=%s assert_action_a3 failure on interface %s", +			__PRETTY_FUNCTION__, ch->sg_str, ifp->name); +		/* warning only */ +	} + +	if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_warn( +				"%s: channel%s not in expected PIM_IFASSERT_I_AM_WINNER state", +				__PRETTY_FUNCTION__, ch->sg_str); +	} + +	return 0;  }  /* @@ -636,24 +629,23 @@ int assert_action_a1(struct pim_ifchannel *ch)    (S,G) Assert State machine Actions       A2:  Store new assert winner as AssertWinner(S,G,I) and assert -          winner metric as AssertWinnerMetric(S,G,I). -          Set Assert Timer to Assert_Time. +	  winner metric as AssertWinnerMetric(S,G,I). +	  Set Assert Timer to Assert_Time.  */  static void assert_action_a2(struct pim_ifchannel *ch,  			     struct pim_assert_metric winner_metric)  { -  pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_LOSER, -			  winner_metric.ip_address, -			  winner_metric); -   -  pim_assert_timer_set(ch, PIM_ASSERT_TIME); - -  if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) -    { -      if (PIM_DEBUG_PIM_EVENTS) -	zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_LOSER state", -		  __PRETTY_FUNCTION__, ch->sg_str); -    } +	pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_LOSER, +				winner_metric.ip_address, winner_metric); + +	pim_assert_timer_set(ch, PIM_ASSERT_TIME); + +	if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_warn( +				"%s: channel%s not in expected PIM_IFASSERT_I_AM_LOSER state", +				__PRETTY_FUNCTION__, ch->sg_str); +	}  }  /* @@ -666,24 +658,23 @@ static void assert_action_a2(struct pim_ifchannel *ch,  */  static int assert_action_a3(struct pim_ifchannel *ch)  { -  if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) -    { -      if (PIM_DEBUG_PIM_EVENTS) -	zlog_warn("%s: channel%s expected to be in PIM_IFASSERT_I_AM_WINNER state", -		  __PRETTY_FUNCTION__, ch->sg_str); -      return -1; -    } - -  pim_assert_timer_reset(ch); - -  if (pim_assert_send(ch)) { -    zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", -	      __PRETTY_FUNCTION__, -	      ch->sg_str, ch->interface->name); -    return -1; -  } - -  return 0; +	if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_warn( +				"%s: channel%s expected to be in PIM_IFASSERT_I_AM_WINNER state", +				__PRETTY_FUNCTION__, ch->sg_str); +		return -1; +	} + +	pim_assert_timer_reset(ch); + +	if (pim_assert_send(ch)) { +		zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", +			  __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); +		return -1; +	} + +	return 0;  }  /* @@ -692,27 +683,26 @@ static int assert_action_a3(struct pim_ifchannel *ch)    (S,G) Assert State machine Actions       A4:  Send AssertCancel(S,G). -          Delete assert info (AssertWinner(S,G,I) and -          AssertWinnerMetric(S,G,I) will then return their default -          values). +	  Delete assert info (AssertWinner(S,G,I) and +	  AssertWinnerMetric(S,G,I) will then return their default +	  values).  */  void assert_action_a4(struct pim_ifchannel *ch)  { -  if (pim_assert_cancel(ch)) { -    zlog_warn("%s: failure sending AssertCancel%s on interface %s", -	      __PRETTY_FUNCTION__, -	      ch->sg_str, ch->interface->name); -    /* log warning only */ -  } - -  assert_action_a5(ch); - -  if (ch->ifassert_state != PIM_IFASSERT_NOINFO) -    { -      if (PIM_DEBUG_PIM_EVENTS) -	zlog_warn("%s: channel%s not in PIM_IFASSERT_NOINFO state as expected", -		  __PRETTY_FUNCTION__, ch->sg_str); -    } +	if (pim_assert_cancel(ch)) { +		zlog_warn("%s: failure sending AssertCancel%s on interface %s", +			  __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); +		/* log warning only */ +	} + +	assert_action_a5(ch); + +	if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_warn( +				"%s: channel%s not in PIM_IFASSERT_NOINFO state as expected", +				__PRETTY_FUNCTION__, ch->sg_str); +	}  }  /* @@ -725,13 +715,13 @@ void assert_action_a4(struct pim_ifchannel *ch)  */  void assert_action_a5(struct pim_ifchannel *ch)  { -  reset_ifassert_state(ch); -  if (ch->ifassert_state != PIM_IFASSERT_NOINFO) -    { -      if (PIM_DEBUG_PIM_EVENTS) -	zlog_warn("%s: channel%s not in PIM_IFSSERT_NOINFO state as expected", -		  __PRETTY_FUNCTION__, ch->sg_str); -    } +	reset_ifassert_state(ch); +	if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_warn( +				"%s: channel%s not in PIM_IFSSERT_NOINFO state as expected", +				__PRETTY_FUNCTION__, ch->sg_str); +	}  }  /* @@ -740,29 +730,28 @@ void assert_action_a5(struct pim_ifchannel *ch)    (S,G) Assert State machine Actions       A6:  Store new assert winner as AssertWinner(S,G,I) and assert -          winner metric as AssertWinnerMetric(S,G,I). -          Set Assert Timer to Assert_Time. -          If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) -          set SPTbit(S,G) to TRUE. +	  winner metric as AssertWinnerMetric(S,G,I). +	  Set Assert Timer to Assert_Time. +	  If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) +	  set SPTbit(S,G) to TRUE.  */  static void assert_action_a6(struct pim_ifchannel *ch,  			     struct pim_assert_metric winner_metric)  { -  assert_action_a2(ch, winner_metric); - -  /* -    If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) set -    SPTbit(S,G) to TRUE. -  */ -  if (ch->upstream->rpf.source_nexthop.interface == ch->interface) -   if (ch->upstream->join_state == PIM_UPSTREAM_JOINED) -     ch->upstream->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - -  if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) -    { -      if(PIM_DEBUG_PIM_EVENTS) -	zlog_warn("%s: channel%s not in PIM_IFASSERT_I_AM_LOSER state as expected", -		  __PRETTY_FUNCTION__, ch->sg_str); -    } +	assert_action_a2(ch, winner_metric); + +	/* +	  If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) set +	  SPTbit(S,G) to TRUE. +	*/ +	if (ch->upstream->rpf.source_nexthop.interface == ch->interface) +		if (ch->upstream->join_state == PIM_UPSTREAM_JOINED) +			ch->upstream->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + +	if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_warn( +				"%s: channel%s not in PIM_IFASSERT_I_AM_LOSER state as expected", +				__PRETTY_FUNCTION__, ch->sg_str); +	}  } - diff --git a/pimd/pim_assert.h b/pimd/pim_assert.h index b2fc115231..63fda3fe34 100644 --- a/pimd/pim_assert.h +++ b/pimd/pim_assert.h @@ -40,27 +40,22 @@  #define PIM_ASSERT_METRIC_PREFERENCE_MAX (0xFFFFFFFF)  #define PIM_ASSERT_ROUTE_METRIC_MAX      (0xFFFFFFFF) -void pim_ifassert_winner_set(struct pim_ifchannel     *ch, -			     enum pim_ifassert_state   new_state, -			     struct in_addr            winner, -			     struct pim_assert_metric  winner_metric); +void pim_ifassert_winner_set(struct pim_ifchannel *ch, +			     enum pim_ifassert_state new_state, +			     struct in_addr winner, +			     struct pim_assert_metric winner_metric); -int pim_assert_recv(struct interface *ifp, -		    struct pim_neighbor *neigh, -		    struct in_addr src_addr, -		    uint8_t *buf, int buf_size); +int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, +		    struct in_addr src_addr, uint8_t *buf, int buf_size);  int pim_assert_metric_better(const struct pim_assert_metric *m1,  			     const struct pim_assert_metric *m2);  int pim_assert_metric_match(const struct pim_assert_metric *m1,  			    const struct pim_assert_metric *m2); -int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, -			 struct interface *ifp, -			 struct in_addr group_addr, -			 struct in_addr source_addr, -			 uint32_t metric_preference, -			 uint32_t route_metric, +int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp, +			 struct in_addr group_addr, struct in_addr source_addr, +			 uint32_t metric_preference, uint32_t route_metric,  			 uint32_t rpt_bit_flag);  int pim_assert_send(struct pim_ifchannel *ch); diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c index af8a8e2c52..e4c50a18be 100644 --- a/pimd/pim_bfd.c +++ b/pimd/pim_bfd.c @@ -38,101 +38,94 @@  /*   * pim_bfd_write_config - Write the interface BFD configuration.   */ -void -pim_bfd_write_config (struct vty *vty, struct interface *ifp) +void pim_bfd_write_config(struct vty *vty, struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct bfd_info *bfd_info = NULL; - -  if (!pim_ifp) -    return; - -  bfd_info = (struct bfd_info *) pim_ifp->bfd_info; -  if (!bfd_info) -    return; - -  if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) -    vty_out (vty, " ip pim bfd %d %d %d\n", -             bfd_info->detect_mult, bfd_info->required_min_rx, -             bfd_info->desired_min_tx); -  else -    vty_out (vty, " ip pim bfd\n"); +	struct pim_interface *pim_ifp = ifp->info; +	struct bfd_info *bfd_info = NULL; + +	if (!pim_ifp) +		return; + +	bfd_info = (struct bfd_info *)pim_ifp->bfd_info; +	if (!bfd_info) +		return; + +	if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) +		vty_out(vty, " ip pim bfd %d %d %d\n", bfd_info->detect_mult, +			bfd_info->required_min_rx, bfd_info->desired_min_tx); +	else +		vty_out(vty, " ip pim bfd\n");  }  /*   * pim_bfd_show_info - Show BFD info structure   */ -void -pim_bfd_show_info (struct vty *vty, void *bfd_info, json_object * json_obj, -                   u_char use_json, int param_only) +void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, +		       u_char use_json, int param_only)  { -  if (param_only) -    bfd_show_param (vty, (struct bfd_info *) bfd_info, 1, 0, use_json, -                    json_obj); -  else -    bfd_show_info (vty, (struct bfd_info *) bfd_info, 0, 1, use_json, -                   json_obj); +	if (param_only) +		bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, +			       json_obj); +	else +		bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, +			      json_obj);  }  /*   * pim_bfd_info_nbr_create - Create/update BFD information for a neighbor.   */ -void -pim_bfd_info_nbr_create (struct pim_interface *pim_ifp, -                         struct pim_neighbor *neigh) +void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp, +			     struct pim_neighbor *neigh)  { -  struct bfd_info *nbr_bfd_info = NULL; +	struct bfd_info *nbr_bfd_info = NULL; -  /* Check if Pim Interface BFD is enabled */ -  if (!pim_ifp || !pim_ifp->bfd_info) -    return; +	/* Check if Pim Interface BFD is enabled */ +	if (!pim_ifp || !pim_ifp->bfd_info) +		return; -  if (!neigh->bfd_info) -    neigh->bfd_info = bfd_info_create (); +	if (!neigh->bfd_info) +		neigh->bfd_info = bfd_info_create(); -  if (!neigh->bfd_info) -    return; +	if (!neigh->bfd_info) +		return; -  nbr_bfd_info = (struct bfd_info *) neigh->bfd_info; -  nbr_bfd_info->detect_mult = pim_ifp->bfd_info->detect_mult; -  nbr_bfd_info->desired_min_tx = pim_ifp->bfd_info->desired_min_tx; -  nbr_bfd_info->required_min_rx = pim_ifp->bfd_info->required_min_rx; +	nbr_bfd_info = (struct bfd_info *)neigh->bfd_info; +	nbr_bfd_info->detect_mult = pim_ifp->bfd_info->detect_mult; +	nbr_bfd_info->desired_min_tx = pim_ifp->bfd_info->desired_min_tx; +	nbr_bfd_info->required_min_rx = pim_ifp->bfd_info->required_min_rx;  }  /*   * pim_bfd_info_free - Free BFD info structure   */ -void -pim_bfd_info_free (void **bfd_info) +void pim_bfd_info_free(void **bfd_info)  { -  bfd_info_free ((struct bfd_info **) bfd_info); +	bfd_info_free((struct bfd_info **)bfd_info);  } -static void -pim_bfd_reg_dereg_nbr (struct pim_neighbor *nbr, int command) +static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command)  { -  struct pim_interface *pim_ifp = NULL; -  struct bfd_info *bfd_info = NULL; -  struct zclient *zclient = NULL; - -  zclient = pim_zebra_zclient_get (); - -  if (!nbr) -    return; -  pim_ifp = nbr->interface->info; -  bfd_info = (struct bfd_info *) pim_ifp->bfd_info; -  if (!bfd_info) -    return; -  if (PIM_DEBUG_PIM_TRACE) -    { -      char str[INET_ADDRSTRLEN]; -      pim_inet4_dump ("<bfd_nbr?>", nbr->source_addr, str, sizeof (str)); -      zlog_debug ("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str, -              bfd_get_command_dbg_str (command)); -    } -  bfd_peer_sendmsg (zclient, bfd_info, AF_INET, -                    &nbr->source_addr, NULL, nbr->interface->name, -                    0, 0, command, 0, VRF_DEFAULT); +	struct pim_interface *pim_ifp = NULL; +	struct bfd_info *bfd_info = NULL; +	struct zclient *zclient = NULL; + +	zclient = pim_zebra_zclient_get(); + +	if (!nbr) +		return; +	pim_ifp = nbr->interface->info; +	bfd_info = (struct bfd_info *)pim_ifp->bfd_info; +	if (!bfd_info) +		return; +	if (PIM_DEBUG_PIM_TRACE) { +		char str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<bfd_nbr?>", nbr->source_addr, str, +			       sizeof(str)); +		zlog_debug("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str, +			   bfd_get_command_dbg_str(command)); +	} +	bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->source_addr, NULL, +			 nbr->interface->name, 0, 0, command, 0, VRF_DEFAULT);  }  /* @@ -141,75 +134,68 @@ pim_bfd_reg_dereg_nbr (struct pim_neighbor *nbr, int command)   *                              zebra for starting/stopping the monitoring of   *                              the neighbor rechahability.   */ -int -pim_bfd_reg_dereg_all_nbr (struct interface *ifp, int command) +int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command)  { -  struct pim_interface *pim_ifp = NULL; -  struct listnode *node = NULL; -  struct pim_neighbor *neigh = NULL; - -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return -1; -  if (!pim_ifp->bfd_info) -    return -1; - -  for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_neighbor_list, node, neigh)) -    { -      if (command != ZEBRA_BFD_DEST_DEREGISTER) -        pim_bfd_info_nbr_create (pim_ifp, neigh); -      else -        bfd_info_free ((struct bfd_info **) &neigh->bfd_info); - -      pim_bfd_reg_dereg_nbr (neigh, command); -    } - -  return 0; +	struct pim_interface *pim_ifp = NULL; +	struct listnode *node = NULL; +	struct pim_neighbor *neigh = NULL; + +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return -1; +	if (!pim_ifp->bfd_info) +		return -1; + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { +		if (command != ZEBRA_BFD_DEST_DEREGISTER) +			pim_bfd_info_nbr_create(pim_ifp, neigh); +		else +			bfd_info_free((struct bfd_info **)&neigh->bfd_info); + +		pim_bfd_reg_dereg_nbr(neigh, command); +	} + +	return 0;  }  /*   * pim_bfd_trigger_event - Neighbor is registered/deregistered with BFD when   *                          neighbor state is changed to/from 2way.   */ -void -pim_bfd_trigger_event (struct pim_interface *pim_ifp, struct pim_neighbor *nbr, uint8_t nbr_up) +void pim_bfd_trigger_event(struct pim_interface *pim_ifp, +			   struct pim_neighbor *nbr, uint8_t nbr_up)  { -  if (nbr_up) -    { -      pim_bfd_info_nbr_create (pim_ifp, nbr); -      pim_bfd_reg_dereg_nbr (nbr, ZEBRA_BFD_DEST_REGISTER); -    } -  else -    { -      pim_bfd_info_free ((void *)&nbr->bfd_info); -      pim_bfd_reg_dereg_nbr (nbr, ZEBRA_BFD_DEST_DEREGISTER); -    } +	if (nbr_up) { +		pim_bfd_info_nbr_create(pim_ifp, nbr); +		pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER); +	} else { +		pim_bfd_info_free((void *)&nbr->bfd_info); +		pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER); +	}  }  /*   * pim_bfd_if_param_set - Set the configured BFD paramter values for   *                         interface.   */ -void -pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, -                      u_int32_t min_tx, u_int8_t detect_mult, int defaults) +void pim_bfd_if_param_set(struct interface *ifp, u_int32_t min_rx, +			  u_int32_t min_tx, u_int8_t detect_mult, int defaults)  { -  struct pim_interface *pim_ifp = ifp->info; -  int command = 0; - -  if (!pim_ifp) -    return; -  bfd_set_param ((struct bfd_info **) &(pim_ifp->bfd_info), min_rx, min_tx, -                 detect_mult, defaults, &command); - -  if (pim_ifp->bfd_info) -    { -      if (PIM_DEBUG_PIM_TRACE) -        zlog_debug ("%s: interface %s has bfd_info", __PRETTY_FUNCTION__, -                    ifp->name); -    } -  if (command) -    pim_bfd_reg_dereg_all_nbr (ifp, command); +	struct pim_interface *pim_ifp = ifp->info; +	int command = 0; + +	if (!pim_ifp) +		return; +	bfd_set_param((struct bfd_info **)&(pim_ifp->bfd_info), min_rx, min_tx, +		      detect_mult, defaults, &command); + +	if (pim_ifp->bfd_info) { +		if (PIM_DEBUG_PIM_TRACE) +			zlog_debug("%s: interface %s has bfd_info", +				   __PRETTY_FUNCTION__, ifp->name); +	} +	if (command) +		pim_bfd_reg_dereg_all_nbr(ifp, command);  } @@ -219,145 +205,133 @@ pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx,   *                                  connectivity if the BFD status changed to   *                                  down.   */ -static int -pim_bfd_interface_dest_update (int command, struct zclient *zclient, -                               zebra_size_t length, vrf_id_t vrf_id) +static int pim_bfd_interface_dest_update(int command, struct zclient *zclient, +					 zebra_size_t length, vrf_id_t vrf_id)  { -  struct interface *ifp = NULL; -  struct pim_interface *pim_ifp = NULL; -  struct prefix p; -  int status; -  char msg[100]; -  int old_status; -  struct bfd_info *bfd_info = NULL; -  struct timeval tv; -  struct listnode *neigh_node = NULL; -  struct listnode *neigh_nextnode = NULL; -  struct pim_neighbor *neigh = NULL; - -  ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL, &status, vrf_id); - -  if ((ifp == NULL) || (p.family != AF_INET)) -    return 0; - -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return 0; - -  if (!pim_ifp->bfd_info) -    { -      if (PIM_DEBUG_PIM_TRACE) -        zlog_debug ("%s: pim interface %s BFD is disabled ", __PRETTY_FUNCTION__, -                    ifp->name); -      return 0; -    } - -  if (PIM_DEBUG_PIM_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      prefix2str (&p, buf, sizeof (buf)); -      zlog_debug ("%s: interface %s bfd destination %s %s", -                  __PRETTY_FUNCTION__, ifp->name, buf, -                  bfd_get_status_str (status)); -    } - -  for (ALL_LIST_ELEMENTS (pim_ifp->pim_neighbor_list, neigh_node, -                          neigh_nextnode, neigh)) -    { -      /* Check neigh address matches with BFD address */ -      if (neigh->source_addr.s_addr != p.u.prefix4.s_addr) -        continue; - -      bfd_info = (struct bfd_info *) neigh->bfd_info; -      if (bfd_info->status == status) -        { -          if (PIM_DEBUG_PIM_TRACE) -            { -              char str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<nht_nbr?>", neigh->source_addr, str, -                              sizeof (str)); -              zlog_debug ("%s: bfd status is same for nbr %s", -                          __PRETTY_FUNCTION__, str); -            } -          continue; -        } -      old_status = bfd_info->status; -      bfd_info->status = status; -      monotime(&tv); -      bfd_info->last_update = tv.tv_sec; - -      if (PIM_DEBUG_PIM_TRACE) -        { -          zlog_debug ("%s: status %s old_status %s", __PRETTY_FUNCTION__, -                      bfd_get_status_str (status), -                      bfd_get_status_str (old_status)); -        } -      if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) -        { -          snprintf (msg, sizeof (msg), "BFD Session Expired"); -          pim_neighbor_delete (ifp, neigh, msg); -        } -    } -  return 0; +	struct interface *ifp = NULL; +	struct pim_interface *pim_ifp = NULL; +	struct prefix p; +	int status; +	char msg[100]; +	int old_status; +	struct bfd_info *bfd_info = NULL; +	struct timeval tv; +	struct listnode *neigh_node = NULL; +	struct listnode *neigh_nextnode = NULL; +	struct pim_neighbor *neigh = NULL; + +	ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id); + +	if ((ifp == NULL) || (p.family != AF_INET)) +		return 0; + +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return 0; + +	if (!pim_ifp->bfd_info) { +		if (PIM_DEBUG_PIM_TRACE) +			zlog_debug("%s: pim interface %s BFD is disabled ", +				   __PRETTY_FUNCTION__, ifp->name); +		return 0; +	} + +	if (PIM_DEBUG_PIM_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		prefix2str(&p, buf, sizeof(buf)); +		zlog_debug("%s: interface %s bfd destination %s %s", +			   __PRETTY_FUNCTION__, ifp->name, buf, +			   bfd_get_status_str(status)); +	} + +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, +			       neigh_nextnode, neigh)) { +		/* Check neigh address matches with BFD address */ +		if (neigh->source_addr.s_addr != p.u.prefix4.s_addr) +			continue; + +		bfd_info = (struct bfd_info *)neigh->bfd_info; +		if (bfd_info->status == status) { +			if (PIM_DEBUG_PIM_TRACE) { +				char str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<nht_nbr?>", neigh->source_addr, +					       str, sizeof(str)); +				zlog_debug("%s: bfd status is same for nbr %s", +					   __PRETTY_FUNCTION__, str); +			} +			continue; +		} +		old_status = bfd_info->status; +		bfd_info->status = status; +		monotime(&tv); +		bfd_info->last_update = tv.tv_sec; + +		if (PIM_DEBUG_PIM_TRACE) { +			zlog_debug("%s: status %s old_status %s", +				   __PRETTY_FUNCTION__, +				   bfd_get_status_str(status), +				   bfd_get_status_str(old_status)); +		} +		if ((status == BFD_STATUS_DOWN) +		    && (old_status == BFD_STATUS_UP)) { +			snprintf(msg, sizeof(msg), "BFD Session Expired"); +			pim_neighbor_delete(ifp, neigh, msg); +		} +	} +	return 0;  }  /*   * pim_bfd_nbr_replay - Replay all the neighbors that have BFD enabled   *                       to zebra   */ -static int -pim_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length, -                    vrf_id_t vrf_id) +static int pim_bfd_nbr_replay(int command, struct zclient *zclient, +			      zebra_size_t length, vrf_id_t vrf_id)  { -  struct interface *ifp = NULL; -  struct pim_interface *pim_ifp = NULL; -  struct pim_neighbor *neigh = NULL; -  struct listnode *node; -  struct listnode *neigh_node; -  struct listnode *neigh_nextnode; - -  /* Send the client registration */ -  bfd_client_sendmsg (zclient, ZEBRA_BFD_CLIENT_REGISTER); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) -    { -      pim_ifp = ifp->info; - -      if (!pim_ifp) -        continue; - -      if (pim_ifp->pim_sock_fd < 0) -        continue; - -      for (ALL_LIST_ELEMENTS (pim_ifp->pim_neighbor_list, neigh_node, -                              neigh_nextnode, neigh)) -        { -          if (!neigh->bfd_info) -            continue; -          if (PIM_DEBUG_PIM_TRACE) -            { -              char str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<bfd_nbr?>", neigh->source_addr, str, -                              sizeof (str)); -              zlog_debug ("%s: Replaying Pim Neigh %s to BFD", -                          __PRETTY_FUNCTION__, str); -            } -          pim_bfd_reg_dereg_nbr (neigh, ZEBRA_BFD_DEST_UPDATE); - -        } -    } -  return 0; +	struct interface *ifp = NULL; +	struct pim_interface *pim_ifp = NULL; +	struct pim_neighbor *neigh = NULL; +	struct listnode *node; +	struct listnode *neigh_node; +	struct listnode *neigh_nextnode; + +	/* Send the client registration */ +	bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (pim_ifp->pim_sock_fd < 0) +			continue; + +		for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, +				       neigh_nextnode, neigh)) { +			if (!neigh->bfd_info) +				continue; +			if (PIM_DEBUG_PIM_TRACE) { +				char str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<bfd_nbr?>", neigh->source_addr, +					       str, sizeof(str)); +				zlog_debug("%s: Replaying Pim Neigh %s to BFD", +					   __PRETTY_FUNCTION__, str); +			} +			pim_bfd_reg_dereg_nbr(neigh, ZEBRA_BFD_DEST_UPDATE); +		} +	} +	return 0;  } -void -pim_bfd_init (void) +void pim_bfd_init(void)  { -  struct zclient *zclient = NULL; +	struct zclient *zclient = NULL; -  zclient = pim_zebra_zclient_get (); +	zclient = pim_zebra_zclient_get(); -  bfd_gbl_init (); +	bfd_gbl_init(); -  zclient->interface_bfd_dest_update = pim_bfd_interface_dest_update; -  zclient->bfd_dest_replay = pim_bfd_nbr_replay; +	zclient->interface_bfd_dest_update = pim_bfd_interface_dest_update; +	zclient->bfd_dest_replay = pim_bfd_nbr_replay;  } diff --git a/pimd/pim_bfd.h b/pimd/pim_bfd.h index 23f286b86e..316d3c1e2f 100644 --- a/pimd/pim_bfd.h +++ b/pimd/pim_bfd.h @@ -25,18 +25,16 @@  #include "if.h" -void pim_bfd_init (void); -void pim_bfd_write_config (struct vty *vty, struct interface *ifp); -void -pim_bfd_show_info (struct vty *vty, void *bfd_info, json_object * json_obj, -                   u_char use_json, int param_only); -void -pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, -                      u_int32_t min_tx, u_int8_t detect_mult, int defaults); -int pim_bfd_reg_dereg_all_nbr (struct interface *ifp, int command); -void -pim_bfd_trigger_event (struct pim_interface *pim_ifp, struct pim_neighbor *nbr, uint8_t nbr_up); -void -pim_bfd_info_nbr_create (struct pim_interface *pim_ifp, struct pim_neighbor *neigh); +void pim_bfd_init(void); +void pim_bfd_write_config(struct vty *vty, struct interface *ifp); +void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, +		       u_char use_json, int param_only); +void pim_bfd_if_param_set(struct interface *ifp, u_int32_t min_rx, +			  u_int32_t min_tx, u_int8_t detect_mult, int defaults); +int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command); +void pim_bfd_trigger_event(struct pim_interface *pim_ifp, +			   struct pim_neighbor *nbr, uint8_t nbr_up); +void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp, +			     struct pim_neighbor *neigh);  void pim_bfd_info_free(void **bfd_info);  #endif /* _PIM_BFD_H */ diff --git a/pimd/pim_br.c b/pimd/pim_br.c index 19a0293c46..f297b0591d 100644 --- a/pimd/pim_br.c +++ b/pimd/pim_br.c @@ -29,83 +29,80 @@  #include "linklist.h"  struct pim_br { -  struct prefix_sg sg; -  struct in_addr pmbr; +	struct prefix_sg sg; +	struct in_addr pmbr;  }; -struct in_addr pim_br_unknown = { .s_addr = 0 }; +struct in_addr pim_br_unknown = {.s_addr = 0};  static struct list *pim_br_list = NULL; -struct in_addr -pim_br_get_pmbr (struct prefix_sg *sg) +struct in_addr pim_br_get_pmbr(struct prefix_sg *sg)  { -  struct listnode *node; -  struct pim_br   *pim_br; +	struct listnode *node; +	struct pim_br *pim_br; -  for (ALL_LIST_ELEMENTS_RO (pim_br_list, node, pim_br)) { -    if (sg->src.s_addr == pim_br->sg.src.s_addr && -	sg->grp.s_addr == pim_br->sg.grp.s_addr) -      return pim_br->pmbr; -  } +	for (ALL_LIST_ELEMENTS_RO(pim_br_list, node, pim_br)) { +		if (sg->src.s_addr == pim_br->sg.src.s_addr +		    && sg->grp.s_addr == pim_br->sg.grp.s_addr) +			return pim_br->pmbr; +	} -  return pim_br_unknown; +	return pim_br_unknown;  } -void -pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr br) +void pim_br_set_pmbr(struct prefix_sg *sg, struct in_addr br)  { -  struct listnode *node, *next; -  struct pim_br *pim_br; +	struct listnode *node, *next; +	struct pim_br *pim_br; -  for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { -    if (sg->src.s_addr == pim_br->sg.src.s_addr && -	sg->grp.s_addr == pim_br->sg.grp.s_addr) -      break; -  } +	for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { +		if (sg->src.s_addr == pim_br->sg.src.s_addr +		    && sg->grp.s_addr == pim_br->sg.grp.s_addr) +			break; +	} -  if (!pim_br) { -    pim_br = XCALLOC(MTYPE_PIM_BR, sizeof (*pim_br)); -    if (!pim_br) { -      zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br)); -      return; -    } +	if (!pim_br) { +		pim_br = XCALLOC(MTYPE_PIM_BR, sizeof(*pim_br)); +		if (!pim_br) { +			zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br)); +			return; +		} -    pim_br->sg = *sg; +		pim_br->sg = *sg; -    listnode_add(pim_br_list, pim_br); -  } +		listnode_add(pim_br_list, pim_br); +	} -  pim_br->pmbr = br; +	pim_br->pmbr = br;  }  /*   * Remove the (S,G) from the stored values   */ -void -pim_br_clear_pmbr (struct prefix_sg *sg) +void pim_br_clear_pmbr(struct prefix_sg *sg)  { -  struct listnode *node, *next; -  struct pim_br *pim_br; +	struct listnode *node, *next; +	struct pim_br *pim_br; -  for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { -    if (sg->src.s_addr == pim_br->sg.src.s_addr && -	sg->grp.s_addr == pim_br->sg.grp.s_addr) -      break; -  } +	for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { +		if (sg->src.s_addr == pim_br->sg.src.s_addr +		    && sg->grp.s_addr == pim_br->sg.grp.s_addr) +			break; +	} -  if (!pim_br) -    return; +	if (!pim_br) +		return; -  listnode_delete (pim_br_list, pim_br); +	listnode_delete(pim_br_list, pim_br);  } -void pim_br_init (void) +void pim_br_init(void)  { -  pim_br_list = list_new(); -  if (!pim_br_list) { -    zlog_err("%s: Failure to create pim_br_list", -	     __PRETTY_FUNCTION__); -    return; -  } +	pim_br_list = list_new(); +	if (!pim_br_list) { +		zlog_err("%s: Failure to create pim_br_list", +			 __PRETTY_FUNCTION__); +		return; +	}  } diff --git a/pimd/pim_br.h b/pimd/pim_br.h index 345dd011e8..836ff5ee83 100644 --- a/pimd/pim_br.h +++ b/pimd/pim_br.h @@ -20,12 +20,12 @@  #ifndef PIM_BR_H  #define PIM_BR_H -struct in_addr pim_br_get_pmbr (struct prefix_sg *sg); +struct in_addr pim_br_get_pmbr(struct prefix_sg *sg); -void pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr value); -void pim_br_clear_pmbr (struct prefix_sg *sg); +void pim_br_set_pmbr(struct prefix_sg *sg, struct in_addr value); +void pim_br_clear_pmbr(struct prefix_sg *sg); -void pim_br_init (void); +void pim_br_init(void);  extern struct in_addr pim_br_unknown; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 88c43104c6..1c9fe40c29 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -61,37 +61,28 @@  #include "bfd.h"  static struct cmd_node pim_global_node = { -  PIM_NODE, -  "", -  1 /* vtysh ? yes */ +	PIM_NODE, "", 1 /* vtysh ? yes */  };  static struct cmd_node interface_node = { -  INTERFACE_NODE, -  "%s(config-if)# ", -  1 /* vtysh ? yes */ +	INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */  }; -static struct cmd_node debug_node = -{ -  DEBUG_NODE, -  "", -  1 -}; +static struct cmd_node debug_node = {DEBUG_NODE, "", 1};  static void pim_if_membership_clear(struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  if (PIM_IF_TEST_PIM(pim_ifp->options) && -      PIM_IF_TEST_IGMP(pim_ifp->options)) { -    return; -  } +	if (PIM_IF_TEST_PIM(pim_ifp->options) +	    && PIM_IF_TEST_IGMP(pim_ifp->options)) { +		return; +	} -  pim_ifchannel_membership_clear(ifp); +	pim_ifchannel_membership_clear(ifp);  }  /* @@ -105,2492 +96,2953 @@ static void pim_if_membership_clear(struct interface *ifp)   */  static void pim_if_membership_refresh(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *sock_node; -  struct igmp_sock     *igmp; +	struct pim_interface *pim_ifp; +	struct listnode *sock_node; +	struct igmp_sock *igmp; -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  if (!PIM_IF_TEST_PIM(pim_ifp->options)) -    return; -  if (!PIM_IF_TEST_IGMP(pim_ifp->options)) -    return; +	if (!PIM_IF_TEST_PIM(pim_ifp->options)) +		return; +	if (!PIM_IF_TEST_IGMP(pim_ifp->options)) +		return; -  /* -    First clear off membership from all PIM (S,G) entries on the -    interface -  */ +	/* +	  First clear off membership from all PIM (S,G) entries on the +	  interface +	*/ -  pim_ifchannel_membership_clear(ifp); +	pim_ifchannel_membership_clear(ifp); -  /* -    Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on -    the interface -  */ +	/* +	  Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on +	  the interface +	*/ -  /* scan igmp sockets */ -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -    struct listnode   *grpnode; -    struct igmp_group *grp; -     -    /* scan igmp groups */ -    for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { -      struct listnode    *srcnode; -      struct igmp_source *src; -       -      /* scan group sources */ -      for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { +	/* scan igmp sockets */ +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { +		struct listnode *grpnode; +		struct igmp_group *grp; -	if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) { -	  struct prefix_sg sg; +		/* scan igmp groups */ +		for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, +					  grp)) { +			struct listnode *srcnode; +			struct igmp_source *src; -	  memset (&sg, 0, sizeof (struct prefix_sg)); -	  sg.src = src->source_addr; -	  sg.grp = grp->group_addr; -	  pim_ifchannel_local_membership_add(ifp, &sg); -	} -	 -      } /* scan group sources */ -    } /* scan igmp groups */ -  } /* scan igmp sockets */ +			/* scan group sources */ +			for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, +						  srcnode, src)) { + +				if (IGMP_SOURCE_TEST_FORWARDING( +					    src->source_flags)) { +					struct prefix_sg sg; + +					memset(&sg, 0, +					       sizeof(struct prefix_sg)); +					sg.src = src->source_addr; +					sg.grp = grp->group_addr; +					pim_ifchannel_local_membership_add(ifp, +									   &sg); +				} -  /* -    Finally delete every PIM (S,G) entry lacking all state info -   */ +			} /* scan group sources */ +		}	 /* scan igmp groups */ +	}		  /* scan igmp sockets */ -  pim_ifchannel_delete_on_noinfo(ifp); +	/* +	  Finally delete every PIM (S,G) entry lacking all state info +	 */ +	pim_ifchannel_delete_on_noinfo(ifp);  }  static void pim_show_assert(struct vty *vty)  { -  struct pim_interface *pim_ifp; -  struct pim_ifchannel *ch; -  struct listnode *ch_node; -  struct in_addr ifaddr; -  time_t now; -   -  now = pim_time_monotonic_sec(); - -  vty_out (vty, -	  "Interface Address         Source          Group           State  Winner          Uptime   Timer\n"); - -  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { -    char ch_src_str[INET_ADDRSTRLEN]; -    char ch_grp_str[INET_ADDRSTRLEN]; -    char winner_str[INET_ADDRSTRLEN]; -    char uptime[10]; -    char timer[10]; - -    pim_ifp = ch->interface->info; -     -    if (!pim_ifp) -      continue; - -    ifaddr = pim_ifp->primary_address; - -    pim_inet4_dump("<ch_src?>", ch->sg.src, -		   ch_src_str, sizeof(ch_src_str)); -    pim_inet4_dump("<ch_grp?>", ch->sg.grp, -		   ch_grp_str, sizeof(ch_grp_str)); -    pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, -		   winner_str, sizeof(winner_str)); - -    pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation); -    pim_time_timer_to_mmss(timer, sizeof(timer), -			   ch->t_ifassert_timer); - -    vty_out (vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n", -	    ch->interface->name, -	    inet_ntoa(ifaddr), -	    ch_src_str, -	    ch_grp_str, -	    pim_ifchannel_ifassert_name(ch->ifassert_state), -	    winner_str, -	    uptime, -	    timer); -  } /* scan interface channels */ +	struct pim_interface *pim_ifp; +	struct pim_ifchannel *ch; +	struct listnode *ch_node; +	struct in_addr ifaddr; +	time_t now; + +	now = pim_time_monotonic_sec(); + +	vty_out(vty, +		"Interface Address         Source          Group           State  Winner          Uptime   Timer\n"); + +	for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { +		char ch_src_str[INET_ADDRSTRLEN]; +		char ch_grp_str[INET_ADDRSTRLEN]; +		char winner_str[INET_ADDRSTRLEN]; +		char uptime[10]; +		char timer[10]; + +		pim_ifp = ch->interface->info; + +		if (!pim_ifp) +			continue; + +		ifaddr = pim_ifp->primary_address; + +		pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, +			       sizeof(ch_src_str)); +		pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, +			       sizeof(ch_grp_str)); +		pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, winner_str, +			       sizeof(winner_str)); + +		pim_time_uptime(uptime, sizeof(uptime), +				now - ch->ifassert_creation); +		pim_time_timer_to_mmss(timer, sizeof(timer), +				       ch->t_ifassert_timer); + +		vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n", +			ch->interface->name, inet_ntoa(ifaddr), ch_src_str, +			ch_grp_str, +			pim_ifchannel_ifassert_name(ch->ifassert_state), +			winner_str, uptime, timer); +	} /* scan interface channels */  }  static void pim_show_assert_internal(struct vty *vty)  { -  struct pim_interface *pim_ifp; -  struct listnode *ch_node; -  struct pim_ifchannel *ch; -  struct in_addr ifaddr; - -  vty_out (vty, -	  "CA:   CouldAssert\n" -	  "ECA:  Evaluate CouldAssert\n" -	  "ATD:  AssertTrackingDesired\n" -	  "eATD: Evaluate AssertTrackingDesired\n\n"); - -  vty_out (vty, -	  "Interface Address         Source          Group           CA  eCA ATD eATD\n"); - -  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { -    pim_ifp = ch->interface->info; -     -    if (!pim_ifp) -      continue; - -    ifaddr = pim_ifp->primary_address; - -    char ch_src_str[INET_ADDRSTRLEN]; -    char ch_grp_str[INET_ADDRSTRLEN]; - -    pim_inet4_dump("<ch_src?>", ch->sg.src, -		   ch_src_str, sizeof(ch_src_str)); -    pim_inet4_dump("<ch_grp?>", ch->sg.grp, -		   ch_grp_str, sizeof(ch_grp_str)); -    vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n", -	    ch->interface->name, -	    inet_ntoa(ifaddr), -	    ch_src_str, -	    ch_grp_str, -	    PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", -	    pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", -	    PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no", -	    pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no"); -  } /* scan interface channels */ +	struct pim_interface *pim_ifp; +	struct listnode *ch_node; +	struct pim_ifchannel *ch; +	struct in_addr ifaddr; + +	vty_out(vty, +		"CA:   CouldAssert\n" +		"ECA:  Evaluate CouldAssert\n" +		"ATD:  AssertTrackingDesired\n" +		"eATD: Evaluate AssertTrackingDesired\n\n"); + +	vty_out(vty, +		"Interface Address         Source          Group           CA  eCA ATD eATD\n"); + +	for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { +		pim_ifp = ch->interface->info; + +		if (!pim_ifp) +			continue; + +		ifaddr = pim_ifp->primary_address; + +		char ch_src_str[INET_ADDRSTRLEN]; +		char ch_grp_str[INET_ADDRSTRLEN]; + +		pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, +			       sizeof(ch_src_str)); +		pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, +			       sizeof(ch_grp_str)); +		vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n", +			ch->interface->name, inet_ntoa(ifaddr), ch_src_str, +			ch_grp_str, +			PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", +			pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", +			PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) +				? "yes" +				: "no", +			pim_macro_assert_tracking_desired_eval(ch) ? "yes" +								   : "no"); +	} /* scan interface channels */  }  static void pim_show_assert_metric(struct vty *vty)  { -  struct pim_interface *pim_ifp; -  struct listnode *ch_node; -  struct pim_ifchannel *ch; -  struct in_addr ifaddr; +	struct pim_interface *pim_ifp; +	struct listnode *ch_node; +	struct pim_ifchannel *ch; +	struct in_addr ifaddr; -  vty_out (vty, -	  "Interface Address         Source          Group           RPT Pref Metric Address        \n"); +	vty_out(vty, +		"Interface Address         Source          Group           RPT Pref Metric Address        \n"); -  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { -    pim_ifp = ch->interface->info; +	for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { +		pim_ifp = ch->interface->info; -    if (!pim_ifp) -      continue; +		if (!pim_ifp) +			continue; -    ifaddr = pim_ifp->primary_address; +		ifaddr = pim_ifp->primary_address; -    char ch_src_str[INET_ADDRSTRLEN]; -    char ch_grp_str[INET_ADDRSTRLEN]; -    char addr_str[INET_ADDRSTRLEN]; -    struct pim_assert_metric am; +		char ch_src_str[INET_ADDRSTRLEN]; +		char ch_grp_str[INET_ADDRSTRLEN]; +		char addr_str[INET_ADDRSTRLEN]; +		struct pim_assert_metric am; -    am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); +		am = pim_macro_spt_assert_metric(&ch->upstream->rpf, +						 pim_ifp->primary_address); -    pim_inet4_dump("<ch_src?>", ch->sg.src, -		   ch_src_str, sizeof(ch_src_str)); -    pim_inet4_dump("<ch_grp?>", ch->sg.grp, -		   ch_grp_str, sizeof(ch_grp_str)); -    pim_inet4_dump("<addr?>", am.ip_address, -		   addr_str, sizeof(addr_str)); +		pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, +			       sizeof(ch_src_str)); +		pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, +			       sizeof(ch_grp_str)); +		pim_inet4_dump("<addr?>", am.ip_address, addr_str, +			       sizeof(addr_str)); -    vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n", -	    ch->interface->name, -	    inet_ntoa(ifaddr), -	    ch_src_str, -	    ch_grp_str, -	    am.rpt_bit_flag ? "yes" : "no", -	    am.metric_preference, -	    am.route_metric, -	    addr_str); -    } /* scan interface channels */ +		vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n", +			ch->interface->name, inet_ntoa(ifaddr), ch_src_str, +			ch_grp_str, am.rpt_bit_flag ? "yes" : "no", +			am.metric_preference, am.route_metric, addr_str); +	} /* scan interface channels */  }  static void pim_show_assert_winner_metric(struct vty *vty)  { -  struct pim_interface *pim_ifp; -  struct listnode *ch_node; -  struct pim_ifchannel *ch; -  struct in_addr ifaddr; -   -  vty_out (vty, -	  "Interface Address         Source          Group           RPT Pref Metric Address        \n"); +	struct pim_interface *pim_ifp; +	struct listnode *ch_node; +	struct pim_ifchannel *ch; +	struct in_addr ifaddr; + +	vty_out(vty, +		"Interface Address         Source          Group           RPT Pref Metric Address        \n"); + +	for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { +		pim_ifp = ch->interface->info; -  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { -    pim_ifp = ch->interface->info; -     -    if (!pim_ifp) -      continue; +		if (!pim_ifp) +			continue; -    ifaddr = pim_ifp->primary_address; +		ifaddr = pim_ifp->primary_address; -    char ch_src_str[INET_ADDRSTRLEN]; -    char ch_grp_str[INET_ADDRSTRLEN]; -    char addr_str[INET_ADDRSTRLEN]; -    struct pim_assert_metric *am; -    char pref_str[5]; -    char metr_str[7]; +		char ch_src_str[INET_ADDRSTRLEN]; +		char ch_grp_str[INET_ADDRSTRLEN]; +		char addr_str[INET_ADDRSTRLEN]; +		struct pim_assert_metric *am; +		char pref_str[5]; +		char metr_str[7]; -    am = &ch->ifassert_winner_metric; +		am = &ch->ifassert_winner_metric; -    pim_inet4_dump("<ch_src?>", ch->sg.src, -		   ch_src_str, sizeof(ch_src_str)); -    pim_inet4_dump("<ch_grp?>", ch->sg.grp, -		   ch_grp_str, sizeof(ch_grp_str)); -    pim_inet4_dump("<addr?>", am->ip_address, -		   addr_str, sizeof(addr_str)); +		pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, +			       sizeof(ch_src_str)); +		pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, +			       sizeof(ch_grp_str)); +		pim_inet4_dump("<addr?>", am->ip_address, addr_str, +			       sizeof(addr_str)); -    if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) -      snprintf(pref_str, sizeof(pref_str), "INFI"); -    else -      snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference); +		if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) +			snprintf(pref_str, sizeof(pref_str), "INFI"); +		else +			snprintf(pref_str, sizeof(pref_str), "%4u", +				 am->metric_preference); -    if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) -      snprintf(metr_str, sizeof(metr_str), "INFI"); -    else -      snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric); +		if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) +			snprintf(metr_str, sizeof(metr_str), "INFI"); +		else +			snprintf(metr_str, sizeof(metr_str), "%6u", +				 am->route_metric); -    vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n", -	    ch->interface->name, -	    inet_ntoa(ifaddr), -	    ch_src_str, -	    ch_grp_str, -	    am->rpt_bit_flag ? "yes" : "no", -	    pref_str, -	    metr_str, -	    addr_str); -  } /* scan interface channels */ +		vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n", +			ch->interface->name, inet_ntoa(ifaddr), ch_src_str, +			ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str, +			metr_str, addr_str); +	} /* scan interface channels */  } -static void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp) +static void json_object_pim_ifp_add(struct json_object *json, +				    struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  pim_ifp = ifp->info; -  json_object_string_add(json, "name", ifp->name); -  json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); -  json_object_string_add(json, "address", inet_ntoa(pim_ifp->primary_address)); -  json_object_int_add(json, "index", ifp->ifindex); +	pim_ifp = ifp->info; +	json_object_string_add(json, "name", ifp->name); +	json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); +	json_object_string_add(json, "address", +			       inet_ntoa(pim_ifp->primary_address)); +	json_object_int_add(json, "index", ifp->ifindex); -  if (if_is_multicast(ifp)) -    json_object_boolean_true_add(json, "flagMulticast"); +	if (if_is_multicast(ifp)) +		json_object_boolean_true_add(json, "flagMulticast"); -  if (if_is_broadcast(ifp)) -    json_object_boolean_true_add(json, "flagBroadcast"); +	if (if_is_broadcast(ifp)) +		json_object_boolean_true_add(json, "flagBroadcast"); -  if (ifp->flags & IFF_ALLMULTI) -    json_object_boolean_true_add(json, "flagAllMulticast"); +	if (ifp->flags & IFF_ALLMULTI) +		json_object_boolean_true_add(json, "flagAllMulticast"); -  if (ifp->flags & IFF_PROMISC) -    json_object_boolean_true_add(json, "flagPromiscuous"); +	if (ifp->flags & IFF_PROMISC) +		json_object_boolean_true_add(json, "flagPromiscuous"); -  if (PIM_IF_IS_DELETED(ifp)) -    json_object_boolean_true_add(json, "flagDeleted"); +	if (PIM_IF_IS_DELETED(ifp)) +		json_object_boolean_true_add(json, "flagDeleted"); -  if (pim_if_lan_delay_enabled(ifp)) -    json_object_boolean_true_add(json, "lanDelayEnabled"); +	if (pim_if_lan_delay_enabled(ifp)) +		json_object_boolean_true_add(json, "lanDelayEnabled");  }  static void pim_show_membership(struct vty *vty, u_char uj)  { -  struct pim_interface *pim_ifp; -  struct listnode *ch_node; -  struct pim_ifchannel *ch; -  enum json_type type; -  json_object *json = NULL; -  json_object *json_iface = NULL; -  json_object *json_row = NULL; -  json_object *json_tmp = NULL; - -  json = json_object_new_object(); - -  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - -    pim_ifp = ch->interface->info; - -    if (!pim_ifp) -      continue; - -    char ch_src_str[INET_ADDRSTRLEN]; -    char ch_grp_str[INET_ADDRSTRLEN]; - -    pim_inet4_dump("<ch_src?>", ch->sg.src, -		   ch_src_str, sizeof(ch_src_str)); -    pim_inet4_dump("<ch_grp?>", ch->sg.grp, -		   ch_grp_str, sizeof(ch_grp_str)); - -    json_object_object_get_ex(json, ch->interface->name, &json_iface); - -    if (!json_iface) { -      json_iface = json_object_new_object(); -      json_object_pim_ifp_add(json_iface, ch->interface); -      json_object_object_add(json, ch->interface->name, json_iface); -    } - -    json_row = json_object_new_object(); -    json_object_string_add(json_row, "source", ch_src_str); -    json_object_string_add(json_row, "group", ch_grp_str); -    json_object_string_add(json_row, "localMembership", -			   ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ?  "NOINFO" : "INCLUDE"); -    json_object_object_add(json_iface, ch_grp_str, json_row); -  } /* scan interface channels */ - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -  } else { -    vty_out (vty, -            "Interface  Address          Source           Group            Membership\n"); - -    /* -     * Example of the json data we are traversing -     * -     * { -     *   "swp3":{ -     *     "name":"swp3", -     *     "state":"up", -     *     "address":"10.1.20.1", -     *     "index":5, -     *     "flagMulticast":true, -     *     "flagBroadcast":true, -     *     "lanDelayEnabled":true, -     *     "226.10.10.10":{ -     *       "source":"*", -     *       "group":"226.10.10.10", -     *       "localMembership":"INCLUDE" -     *     } -     *   } -     * } -     */ - -    /* foreach interface */ -    json_object_object_foreach(json, key, val) { - -      /* Find all of the keys where the val is an object. In the example -       * above the only one is 226.10.10.10 -       */ -      json_object_object_foreach(val, if_field_key, if_field_val) { -        type = json_object_get_type(if_field_val); - -        if (type == json_type_object) { -          vty_out(vty, "%-9s  ", key); - -          json_object_object_get_ex(val, "address", &json_tmp); -          vty_out(vty, "%-15s  ", json_object_get_string(json_tmp)); - -          json_object_object_get_ex(if_field_val, "source", &json_tmp); -          vty_out(vty, "%-15s  ", json_object_get_string(json_tmp)); - -          /* Group */ -          vty_out(vty, "%-15s  ", if_field_key); - -          json_object_object_get_ex(if_field_val, "localMembership", &json_tmp); -          vty_out (vty, "%-10s\n", json_object_get_string(json_tmp)); -        } -      } -    } -  } - -  json_object_free(json); -} - -static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloop) -{ -  vty_out (vty, "Flags\n"); -  vty_out (vty, "-----\n"); -  vty_out (vty, "All Multicast   : %s\n", -            (ifp->flags & IFF_ALLMULTI) ? "yes" : "no"); -  vty_out (vty, "Broadcast       : %s\n", -            if_is_broadcast(ifp) ? "yes" : "no"); -  vty_out (vty, "Deleted         : %s\n", -            PIM_IF_IS_DELETED(ifp) ? "yes" : "no"); -  vty_out (vty, "Interface Index : %d\n", ifp->ifindex); -  vty_out (vty, "Multicast       : %s\n", -            if_is_multicast(ifp) ? "yes" : "no"); -  vty_out (vty, "Multicast Loop  : %d\n", mloop); -  vty_out (vty, "Promiscuous     : %s\n", -            (ifp->flags & IFF_PROMISC) ? "yes" : "no"); -  vty_out (vty, "\n"); -  vty_out (vty, "\n"); +	struct pim_interface *pim_ifp; +	struct listnode *ch_node; +	struct pim_ifchannel *ch; +	enum json_type type; +	json_object *json = NULL; +	json_object *json_iface = NULL; +	json_object *json_row = NULL; +	json_object *json_tmp = NULL; + +	json = json_object_new_object(); + +	for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + +		pim_ifp = ch->interface->info; + +		if (!pim_ifp) +			continue; + +		char ch_src_str[INET_ADDRSTRLEN]; +		char ch_grp_str[INET_ADDRSTRLEN]; + +		pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, +			       sizeof(ch_src_str)); +		pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, +			       sizeof(ch_grp_str)); + +		json_object_object_get_ex(json, ch->interface->name, +					  &json_iface); + +		if (!json_iface) { +			json_iface = json_object_new_object(); +			json_object_pim_ifp_add(json_iface, ch->interface); +			json_object_object_add(json, ch->interface->name, +					       json_iface); +		} + +		json_row = json_object_new_object(); +		json_object_string_add(json_row, "source", ch_src_str); +		json_object_string_add(json_row, "group", ch_grp_str); +		json_object_string_add( +			json_row, "localMembership", +			ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO +				? "NOINFO" +				: "INCLUDE"); +		json_object_object_add(json_iface, ch_grp_str, json_row); +	} /* scan interface channels */ + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +	} else { +		vty_out(vty, +			"Interface  Address          Source           Group            Membership\n"); + +		/* +		 * Example of the json data we are traversing +		 * +		 * { +		 *   "swp3":{ +		 *     "name":"swp3", +		 *     "state":"up", +		 *     "address":"10.1.20.1", +		 *     "index":5, +		 *     "flagMulticast":true, +		 *     "flagBroadcast":true, +		 *     "lanDelayEnabled":true, +		 *     "226.10.10.10":{ +		 *       "source":"*", +		 *       "group":"226.10.10.10", +		 *       "localMembership":"INCLUDE" +		 *     } +		 *   } +		 * } +		 */ + +		/* foreach interface */ +		json_object_object_foreach(json, key, val) +		{ + +			/* Find all of the keys where the val is an object. In +			 * the example +			 * above the only one is 226.10.10.10 +			 */ +			json_object_object_foreach(val, if_field_key, +						   if_field_val) +			{ +				type = json_object_get_type(if_field_val); + +				if (type == json_type_object) { +					vty_out(vty, "%-9s  ", key); + +					json_object_object_get_ex( +						val, "address", &json_tmp); +					vty_out(vty, "%-15s  ", +						json_object_get_string( +							json_tmp)); + +					json_object_object_get_ex(if_field_val, +								  "source", +								  &json_tmp); +					vty_out(vty, "%-15s  ", +						json_object_get_string( +							json_tmp)); + +					/* Group */ +					vty_out(vty, "%-15s  ", if_field_key); + +					json_object_object_get_ex( +						if_field_val, "localMembership", +						&json_tmp); +					vty_out(vty, "%-10s\n", +						json_object_get_string( +							json_tmp)); +				} +			} +		} +	} + +	json_object_free(json); +} + +static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, +				int mloop) +{ +	vty_out(vty, "Flags\n"); +	vty_out(vty, "-----\n"); +	vty_out(vty, "All Multicast   : %s\n", +		(ifp->flags & IFF_ALLMULTI) ? "yes" : "no"); +	vty_out(vty, "Broadcast       : %s\n", +		if_is_broadcast(ifp) ? "yes" : "no"); +	vty_out(vty, "Deleted         : %s\n", +		PIM_IF_IS_DELETED(ifp) ? "yes" : "no"); +	vty_out(vty, "Interface Index : %d\n", ifp->ifindex); +	vty_out(vty, "Multicast       : %s\n", +		if_is_multicast(ifp) ? "yes" : "no"); +	vty_out(vty, "Multicast Loop  : %d\n", mloop); +	vty_out(vty, "Promiscuous     : %s\n", +		(ifp->flags & IFF_PROMISC) ? "yes" : "no"); +	vty_out(vty, "\n"); +	vty_out(vty, "\n");  }  static void igmp_show_interfaces(struct vty *vty, u_char uj)  { -  struct listnode  *node; -  struct interface *ifp; -  time_t            now; -  json_object *json = NULL; -  json_object *json_row = NULL; - -  now = pim_time_monotonic_sec(); - -  if (uj) -    json = json_object_new_object(); -  else -    vty_out (vty, -            "Interface  State          Address  V  Querier  Query Timer    Uptime\n"); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    struct pim_interface *pim_ifp; -    struct listnode *sock_node; -    struct igmp_sock *igmp; - -    pim_ifp = ifp->info; - -    if (!pim_ifp) -      continue; - -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -      char uptime[10]; -      char query_hhmmss[10]; - -      pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); -      pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); - -      if (uj) { -        json_row = json_object_new_object(); -        json_object_pim_ifp_add(json_row, ifp); -        json_object_string_add(json_row, "upTime", uptime); -        json_object_int_add(json_row, "version", pim_ifp->igmp_version); - -        if (igmp->t_igmp_query_timer) { -          json_object_boolean_true_add(json_row, "querier"); -          json_object_string_add(json_row, "queryTimer", query_hhmmss); -        } - -        json_object_object_add(json, ifp->name, json_row); - -      } else { -        vty_out (vty, "%-9s  %5s  %15s  %d  %7s  %11s  %8s\n", -                ifp->name, -                if_is_up(ifp) ? "up" : "down", -                inet_ntoa(igmp->ifaddr), -                pim_ifp->igmp_version, -	        igmp->t_igmp_query_timer ? "local" : "other", -	        query_hhmmss, -                uptime); -      } -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } -} - -static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) -{ -  struct igmp_sock *igmp; -  struct interface *ifp; -  struct listnode  *node; -  struct listnode *sock_node; -  struct pim_interface *pim_ifp; -  char uptime[10]; -  char query_hhmmss[10]; -  char other_hhmmss[10]; -  int found_ifname = 0; -  int sqi; -  int mloop; -  long gmi_msec;  /* Group Membership Interval */ -  long lmqt_msec; -  long ohpi_msec; -  long oqpi_msec; /* Other Querier Present Interval */ -  long qri_msec; -  time_t now; - -  json_object *json = NULL; -  json_object *json_row = NULL; - -  if (uj) -    json = json_object_new_object(); - -  now = pim_time_monotonic_sec(); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    pim_ifp = ifp->info; - -    if (!pim_ifp) -      continue; - -    if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) -      continue; - -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -      found_ifname = 1; -      pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); -      pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); -      pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer); - -      gmi_msec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, -                                   igmp->querier_query_interval, -                                   pim_ifp->igmp_query_max_response_time_dsec); - -      sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - -      oqpi_msec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, -                                     igmp->querier_query_interval, -                                     pim_ifp->igmp_query_max_response_time_dsec); - -      lmqt_msec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec, -                                     igmp->querier_robustness_variable); - -      ohpi_msec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable, -                                     igmp->querier_query_interval, -                                     pim_ifp->igmp_query_max_response_time_dsec) * 100; - -      qri_msec = pim_ifp->igmp_query_max_response_time_dsec * 100; -      mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - -      if (uj) { -        json_row = json_object_new_object(); -        json_object_pim_ifp_add(json_row, ifp); -        json_object_string_add(json_row, "upTime", uptime); -        json_object_string_add(json_row, "querier", igmp->t_igmp_query_timer ? "local" : "other"); -        json_object_int_add(json_row, "queryStartCount", igmp->startup_query_count); -        json_object_string_add(json_row, "queryQueryTimer", query_hhmmss); -        json_object_string_add(json_row, "queryOtherTimer", other_hhmmss); -        json_object_int_add(json_row, "version", pim_ifp->igmp_version); -        json_object_int_add(json_row, "timerGroupMembershipIntervalMsec", gmi_msec); -        json_object_int_add(json_row, "timerLastMemberQueryMsec", lmqt_msec); -        json_object_int_add(json_row, "timerOlderHostPresentIntervalMsec", ohpi_msec); -        json_object_int_add(json_row, "timerOtherQuerierPresentIntervalMsec", oqpi_msec); -        json_object_int_add(json_row, "timerQueryInterval", igmp->querier_query_interval); -        json_object_int_add(json_row, "timerQueryResponseIntervalMsec", qri_msec); -        json_object_int_add(json_row, "timerRobustnessVariable", igmp->querier_robustness_variable); -        json_object_int_add(json_row, "timerStartupQueryInterval", sqi); - -        json_object_object_add(json, ifp->name, json_row); - -      } else { -        vty_out (vty, "Interface : %s\n", ifp->name); -        vty_out (vty, "State     : %s\n", if_is_up(ifp) ? "up" : "down"); -        vty_out (vty, "Address   : %s\n", -                  inet_ntoa(pim_ifp->primary_address)); -        vty_out (vty, "Uptime    : %s\n", uptime); -        vty_out (vty, "Version   : %d\n", pim_ifp->igmp_version); -        vty_out (vty, "\n"); -        vty_out (vty, "\n"); - -        vty_out (vty, "Querier\n"); -        vty_out (vty, "-------\n"); -        vty_out (vty, "Querier     : %s\n", -                  igmp->t_igmp_query_timer ? "local" : "other"); -        vty_out (vty, "Start Count : %d\n", igmp->startup_query_count); -        vty_out (vty, "Query Timer : %s\n", query_hhmmss); -        vty_out (vty, "Other Timer : %s\n", other_hhmmss); -        vty_out (vty, "\n"); -        vty_out (vty, "\n"); - -        vty_out (vty, "Timers\n"); -        vty_out (vty, "------\n"); -        vty_out (vty, "Group Membership Interval      : %lis\n", -                  gmi_msec / 1000); -        vty_out (vty, "Last Member Query Time         : %lis\n", -                  lmqt_msec / 1000); -        vty_out (vty, "Older Host Present Interval    : %lis\n", -                  ohpi_msec / 1000); -        vty_out (vty, "Other Querier Present Interval : %lis\n", -                  oqpi_msec / 1000); -        vty_out (vty, "Query Interval                 : %ds\n", -                  igmp->querier_query_interval); -        vty_out (vty, "Query Response Interval        : %lis\n", -                  qri_msec / 1000); -        vty_out (vty, "Robustness Variable            : %d\n", -                  igmp->querier_robustness_variable); -        vty_out (vty, "Startup Query Interval         : %ds\n", sqi); -        vty_out (vty, "\n"); -        vty_out (vty, "\n"); - -        pim_print_ifp_flags(vty, ifp, mloop); -      } -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } else { -    if (!found_ifname) -      vty_out (vty, "%% No such interface\n"); -  } +	struct listnode *node; +	struct interface *ifp; +	time_t now; +	json_object *json = NULL; +	json_object *json_row = NULL; + +	now = pim_time_monotonic_sec(); + +	if (uj) +		json = json_object_new_object(); +	else +		vty_out(vty, +			"Interface  State          Address  V  Querier  Query Timer    Uptime\n"); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		struct pim_interface *pim_ifp; +		struct listnode *sock_node; +		struct igmp_sock *igmp; + +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, +					  igmp)) { +			char uptime[10]; +			char query_hhmmss[10]; + +			pim_time_uptime(uptime, sizeof(uptime), +					now - igmp->sock_creation); +			pim_time_timer_to_hhmmss(query_hhmmss, +						 sizeof(query_hhmmss), +						 igmp->t_igmp_query_timer); + +			if (uj) { +				json_row = json_object_new_object(); +				json_object_pim_ifp_add(json_row, ifp); +				json_object_string_add(json_row, "upTime", +						       uptime); +				json_object_int_add(json_row, "version", +						    pim_ifp->igmp_version); + +				if (igmp->t_igmp_query_timer) { +					json_object_boolean_true_add(json_row, +								     "querier"); +					json_object_string_add(json_row, +							       "queryTimer", +							       query_hhmmss); +				} + +				json_object_object_add(json, ifp->name, +						       json_row); + +			} else { +				vty_out(vty, +					"%-9s  %5s  %15s  %d  %7s  %11s  %8s\n", +					ifp->name, +					if_is_up(ifp) ? "up" : "down", +					inet_ntoa(igmp->ifaddr), +					pim_ifp->igmp_version, +					igmp->t_igmp_query_timer ? "local" +								 : "other", +					query_hhmmss, uptime); +			} +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} +} + +static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, +					u_char uj) +{ +	struct igmp_sock *igmp; +	struct interface *ifp; +	struct listnode *node; +	struct listnode *sock_node; +	struct pim_interface *pim_ifp; +	char uptime[10]; +	char query_hhmmss[10]; +	char other_hhmmss[10]; +	int found_ifname = 0; +	int sqi; +	int mloop; +	long gmi_msec; /* Group Membership Interval */ +	long lmqt_msec; +	long ohpi_msec; +	long oqpi_msec; /* Other Querier Present Interval */ +	long qri_msec; +	time_t now; + +	json_object *json = NULL; +	json_object *json_row = NULL; + +	if (uj) +		json = json_object_new_object(); + +	now = pim_time_monotonic_sec(); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) +			continue; + +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, +					  igmp)) { +			found_ifname = 1; +			pim_time_uptime(uptime, sizeof(uptime), +					now - igmp->sock_creation); +			pim_time_timer_to_hhmmss(query_hhmmss, +						 sizeof(query_hhmmss), +						 igmp->t_igmp_query_timer); +			pim_time_timer_to_hhmmss(other_hhmmss, +						 sizeof(other_hhmmss), +						 igmp->t_other_querier_timer); + +			gmi_msec = PIM_IGMP_GMI_MSEC( +				igmp->querier_robustness_variable, +				igmp->querier_query_interval, +				pim_ifp->igmp_query_max_response_time_dsec); + +			sqi = PIM_IGMP_SQI( +				pim_ifp->igmp_default_query_interval); + +			oqpi_msec = PIM_IGMP_OQPI_MSEC( +				igmp->querier_robustness_variable, +				igmp->querier_query_interval, +				pim_ifp->igmp_query_max_response_time_dsec); + +			lmqt_msec = PIM_IGMP_LMQT_MSEC( +				pim_ifp->igmp_query_max_response_time_dsec, +				igmp->querier_robustness_variable); + +			ohpi_msec = +				PIM_IGMP_OHPI_DSEC( +					igmp->querier_robustness_variable, +					igmp->querier_query_interval, +					pim_ifp->igmp_query_max_response_time_dsec) +				* 100; + +			qri_msec = pim_ifp->igmp_query_max_response_time_dsec +				   * 100; +			mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); + +			if (uj) { +				json_row = json_object_new_object(); +				json_object_pim_ifp_add(json_row, ifp); +				json_object_string_add(json_row, "upTime", +						       uptime); +				json_object_string_add(json_row, "querier", +						       igmp->t_igmp_query_timer +							       ? "local" +							       : "other"); +				json_object_int_add(json_row, "queryStartCount", +						    igmp->startup_query_count); +				json_object_string_add(json_row, +						       "queryQueryTimer", +						       query_hhmmss); +				json_object_string_add(json_row, +						       "queryOtherTimer", +						       other_hhmmss); +				json_object_int_add(json_row, "version", +						    pim_ifp->igmp_version); +				json_object_int_add( +					json_row, +					"timerGroupMembershipIntervalMsec", +					gmi_msec); +				json_object_int_add(json_row, +						    "timerLastMemberQueryMsec", +						    lmqt_msec); +				json_object_int_add( +					json_row, +					"timerOlderHostPresentIntervalMsec", +					ohpi_msec); +				json_object_int_add( +					json_row, +					"timerOtherQuerierPresentIntervalMsec", +					oqpi_msec); +				json_object_int_add( +					json_row, "timerQueryInterval", +					igmp->querier_query_interval); +				json_object_int_add( +					json_row, +					"timerQueryResponseIntervalMsec", +					qri_msec); +				json_object_int_add( +					json_row, "timerRobustnessVariable", +					igmp->querier_robustness_variable); +				json_object_int_add(json_row, +						    "timerStartupQueryInterval", +						    sqi); + +				json_object_object_add(json, ifp->name, +						       json_row); + +			} else { +				vty_out(vty, "Interface : %s\n", ifp->name); +				vty_out(vty, "State     : %s\n", +					if_is_up(ifp) ? "up" : "down"); +				vty_out(vty, "Address   : %s\n", +					inet_ntoa(pim_ifp->primary_address)); +				vty_out(vty, "Uptime    : %s\n", uptime); +				vty_out(vty, "Version   : %d\n", +					pim_ifp->igmp_version); +				vty_out(vty, "\n"); +				vty_out(vty, "\n"); + +				vty_out(vty, "Querier\n"); +				vty_out(vty, "-------\n"); +				vty_out(vty, "Querier     : %s\n", +					igmp->t_igmp_query_timer ? "local" +								 : "other"); +				vty_out(vty, "Start Count : %d\n", +					igmp->startup_query_count); +				vty_out(vty, "Query Timer : %s\n", +					query_hhmmss); +				vty_out(vty, "Other Timer : %s\n", +					other_hhmmss); +				vty_out(vty, "\n"); +				vty_out(vty, "\n"); + +				vty_out(vty, "Timers\n"); +				vty_out(vty, "------\n"); +				vty_out(vty, +					"Group Membership Interval      : %lis\n", +					gmi_msec / 1000); +				vty_out(vty, +					"Last Member Query Time         : %lis\n", +					lmqt_msec / 1000); +				vty_out(vty, +					"Older Host Present Interval    : %lis\n", +					ohpi_msec / 1000); +				vty_out(vty, +					"Other Querier Present Interval : %lis\n", +					oqpi_msec / 1000); +				vty_out(vty, +					"Query Interval                 : %ds\n", +					igmp->querier_query_interval); +				vty_out(vty, +					"Query Response Interval        : %lis\n", +					qri_msec / 1000); +				vty_out(vty, +					"Robustness Variable            : %d\n", +					igmp->querier_robustness_variable); +				vty_out(vty, +					"Startup Query Interval         : %ds\n", +					sqi); +				vty_out(vty, "\n"); +				vty_out(vty, "\n"); + +				pim_print_ifp_flags(vty, ifp, mloop); +			} +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} else { +		if (!found_ifname) +			vty_out(vty, "%% No such interface\n"); +	}  }  static void igmp_show_interface_join(struct vty *vty)  { -  struct listnode  *node; -  struct interface *ifp; -  time_t            now; -   -  now = pim_time_monotonic_sec(); - -  vty_out (vty, -	  "Interface Address         Source          Group           Socket Uptime  \n"); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    struct pim_interface *pim_ifp; -    struct listnode *join_node; -    struct igmp_join *ij; -    struct in_addr pri_addr; -    char pri_addr_str[INET_ADDRSTRLEN]; - -    pim_ifp = ifp->info; -     -    if (!pim_ifp) -      continue; - -    if (!pim_ifp->igmp_join_list) -      continue; - -    pri_addr = pim_find_primary_addr(ifp); -    pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str)); - -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, ij)) { -      char group_str[INET_ADDRSTRLEN]; -      char source_str[INET_ADDRSTRLEN]; -      char uptime[10]; - -      pim_time_uptime(uptime, sizeof(uptime), now - ij->sock_creation); -      pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str)); -      pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str)); -       -      vty_out (vty, "%-9s %-15s %-15s %-15s %6d %8s\n", -	      ifp->name, -	      pri_addr_str, -	      source_str, -	      group_str, -	      ij->sock_fd, -	      uptime); -    } /* for (pim_ifp->igmp_join_list) */ - -  } /* for (iflist) */ - -} - -static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) -{ -  struct in_addr ifaddr; -  struct interface *ifp; -  struct listnode *neighnode; -  struct listnode*node; -  struct listnode *upnode; -  struct pim_interface *pim_ifp; -  struct pim_neighbor *neigh; -  struct pim_upstream *up; -  time_t now; -  char dr_str[INET_ADDRSTRLEN]; -  char dr_uptime[10]; -  char expire[10]; -  char grp_str[INET_ADDRSTRLEN]; -  char hello_period[10]; -  char hello_timer[10]; -  char neigh_src_str[INET_ADDRSTRLEN]; -  char src_str[INET_ADDRSTRLEN]; -  char stat_uptime[10]; -  char uptime[10]; -  int mloop; -  int found_ifname = 0; -  int print_header; -  json_object *json = NULL; -  json_object *json_row = NULL; -  json_object *json_pim_neighbor = NULL; -  json_object *json_pim_neighbors = NULL; -  json_object *json_group = NULL; -  json_object *json_group_source = NULL; -  json_object *json_fhr_sources = NULL; -  struct pim_secondary_addr *sec_addr; -  struct listnode *sec_node; - -  now = pim_time_monotonic_sec(); - -  if (uj) -    json = json_object_new_object(); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    pim_ifp = ifp->info; - -    if (!pim_ifp) -      continue; - -    if (pim_ifp->pim_sock_fd < 0) -      continue; - -    if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) -      continue; - -    found_ifname = 1; -    ifaddr = pim_ifp->primary_address; -    pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str, sizeof(dr_str)); -    pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, pim_ifp->pim_dr_election_last); -    pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer); -    pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period); -    pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start); -    mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - -    if (uj) { -      char pbuf[PREFIX2STR_BUFFER]; -      json_row = json_object_new_object(); -      json_object_pim_ifp_add(json_row, ifp); - -      if (pim_ifp->update_source.s_addr != INADDR_ANY) { -        json_object_string_add(json_row, "useSource", inet_ntoa(pim_ifp->update_source)); -      } -      if (pim_ifp->sec_addr_list) { -        json_object *sec_list = NULL; - -        sec_list = json_object_new_array(); -        for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { -          json_object_array_add(sec_list, -                                json_object_new_string(prefix2str(&sec_addr->addr, -								  pbuf, -								  sizeof(pbuf)))); -        } -        json_object_object_add(json_row, "secondaryAddressList", sec_list); -      } - -      // PIM neighbors -      if (pim_ifp->pim_neighbor_list->count) { -        json_pim_neighbors = json_object_new_object(); - -        for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { -          json_pim_neighbor = json_object_new_object(); -          pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); -          pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); -          pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - -          json_object_string_add(json_pim_neighbor, "address", neigh_src_str); -          json_object_string_add(json_pim_neighbor, "upTime", uptime); -          json_object_string_add(json_pim_neighbor, "holdtime", expire); - -          json_object_object_add(json_pim_neighbors, neigh_src_str, json_pim_neighbor); -        } - -        json_object_object_add(json_row, "neighbors", json_pim_neighbors); -      } - -      json_object_string_add(json_row, "drAddress", dr_str); -      json_object_int_add(json_row, "drPriority", pim_ifp->pim_dr_priority); -      json_object_string_add(json_row, "drUptime", dr_uptime); -      json_object_int_add(json_row, "drElections", pim_ifp->pim_dr_election_count); -      json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes); - -      // FHR -      for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { -        if (ifp ==  up->rpf.source_nexthop.interface) { -          if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { -            if (!json_fhr_sources) { -              json_fhr_sources = json_object_new_object(); -            } - -            pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); -            pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); -            pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - -            /* Does this group live in json_fhr_sources?  If not create it. */ -            json_object_object_get_ex(json_fhr_sources, grp_str, &json_group); - -            if (!json_group) { -                json_group = json_object_new_object(); -                json_object_object_add(json_fhr_sources, grp_str, json_group); -            } - -            json_group_source = json_object_new_object(); -            json_object_string_add(json_group_source, "source", src_str); -            json_object_string_add(json_group_source, "group", grp_str); -            json_object_string_add(json_group_source, "upTime", uptime); -            json_object_object_add(json_group, src_str, json_group_source); -          } -        } -      } - -      if (json_fhr_sources) { -        json_object_object_add(json_row, "firstHopRouter", json_fhr_sources); -      } - -      json_object_int_add(json_row, "helloPeriod", pim_ifp->pim_hello_period); -      json_object_string_add(json_row, "helloTimer", hello_timer); -      json_object_string_add(json_row, "helloStatStart", stat_uptime); -      json_object_int_add(json_row, "helloReceived", pim_ifp->pim_ifstat_hello_recv); -      json_object_int_add(json_row, "helloReceivedFailed", pim_ifp->pim_ifstat_hello_recvfail); -      json_object_int_add(json_row, "helloSend", pim_ifp->pim_ifstat_hello_sent); -      json_object_int_add(json_row, "hellosendFailed", pim_ifp->pim_ifstat_hello_sendfail); -      json_object_int_add(json_row, "helloGenerationId", pim_ifp->pim_generation_id); -      json_object_int_add(json_row, "flagMulticastLoop", mloop); - -      json_object_int_add(json_row, "effectivePropagationDelay", pim_if_effective_propagation_delay_msec(ifp)); -      json_object_int_add(json_row, "effectiveOverrideInterval", pim_if_effective_override_interval_msec(ifp)); -      json_object_int_add(json_row, "joinPruneOverrideInterval", pim_if_jp_override_interval_msec(ifp)); - -      json_object_int_add(json_row, "propagationDelay", pim_ifp->pim_propagation_delay_msec); -      json_object_int_add(json_row, "propagationDelayHighest", pim_ifp->pim_neighbors_highest_propagation_delay_msec); -      json_object_int_add(json_row, "overrideInterval", pim_ifp->pim_override_interval_msec); -      json_object_int_add(json_row, "overrideIntervalHighest", pim_ifp->pim_neighbors_highest_override_interval_msec); -      json_object_object_add(json, ifp->name, json_row); - -    } else { -      vty_out (vty, "Interface  : %s\n", ifp->name); -      vty_out (vty, "State      : %s\n", if_is_up(ifp) ? "up" : "down"); -      if (pim_ifp->update_source.s_addr != INADDR_ANY) { -        vty_out (vty, "Use Source : %s\n", inet_ntoa(pim_ifp->update_source)); -      } -      if (pim_ifp->sec_addr_list) { -        char pbuf[PREFIX2STR_BUFFER]; -        vty_out (vty, "Address    : %s (primary)\n", -                inet_ntoa(ifaddr)); -        for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { -          vty_out (vty, "             %s\n", -                  prefix2str(&sec_addr->addr, pbuf, sizeof(pbuf))); -        } -      } else { -        vty_out (vty, "Address    : %s\n", inet_ntoa(ifaddr)); -      } -      vty_out (vty, "\n"); - -      // PIM neighbors -      print_header = 1; - -      for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - -        if (print_header) { -          vty_out (vty, "PIM Neighbors\n"); -          vty_out (vty, "-------------\n"); -          print_header = 0; -        } - -        pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); -        pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); -        pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); -        vty_out (vty, "%-15s : up for %s, holdtime expires in %s\n", neigh_src_str, uptime, -                  expire); -      } - -      if (!print_header) { -        vty_out (vty, "\n"); -        vty_out (vty, "\n"); -      } - -      vty_out (vty, "Designated Router\n"); -      vty_out (vty, "-----------------\n"); -      vty_out (vty, "Address   : %s\n", dr_str); -      vty_out (vty, "Priority  : %d\n", pim_ifp->pim_dr_priority); -      vty_out (vty, "Uptime    : %s\n", dr_uptime); -      vty_out (vty, "Elections : %d\n", pim_ifp->pim_dr_election_count); -      vty_out (vty, "Changes   : %d\n", pim_ifp->pim_dr_election_changes); -      vty_out (vty, "\n"); -      vty_out (vty, "\n"); - -      // FHR -      print_header = 1; -      for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { -        if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) { -          if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { - -            if (print_header) { -              vty_out (vty, "FHR - First Hop Router\n"); -              vty_out (vty, "----------------------\n"); -              print_header = 0; -            } - -            pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); -            pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); -            pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); -            vty_out (vty, "%s : %s is a source, uptime is %s\n", grp_str, src_str, -                      uptime); -          } -        } -      } - -      if (!print_header) { -        vty_out (vty, "\n"); -        vty_out (vty, "\n"); -      } - -      vty_out (vty, "Hellos\n"); -      vty_out (vty, "------\n"); -      vty_out (vty, "Period         : %d\n", pim_ifp->pim_hello_period); -      vty_out (vty, "Timer          : %s\n", hello_timer); -      vty_out (vty, "StatStart      : %s\n", stat_uptime); -      vty_out (vty, "Receive        : %d\n", pim_ifp->pim_ifstat_hello_recv); -      vty_out (vty, "Receive Failed : %d\n", -                pim_ifp->pim_ifstat_hello_recvfail); -      vty_out (vty, "Send           : %d\n", pim_ifp->pim_ifstat_hello_sent); -      vty_out (vty, "Send Failed    : %d\n", -                pim_ifp->pim_ifstat_hello_sendfail); -      vty_out (vty, "Generation ID  : %08x\n", pim_ifp->pim_generation_id); -      vty_out (vty, "\n"); -      vty_out (vty, "\n"); - -      pim_print_ifp_flags(vty, ifp, mloop); - -      vty_out (vty, "Join Prune Interval\n"); -      vty_out (vty, "-------------------\n"); -      vty_out (vty, "LAN Delay                    : %s\n", -                pim_if_lan_delay_enabled(ifp) ? "yes" : "no"); -      vty_out (vty, "Effective Propagation Delay  : %d msec\n", -                pim_if_effective_propagation_delay_msec(ifp)); -      vty_out (vty, "Effective Override Interval  : %d msec\n", -                pim_if_effective_override_interval_msec(ifp)); -      vty_out (vty, "Join Prune Override Interval : %d msec\n", -                pim_if_jp_override_interval_msec(ifp)); -      vty_out (vty, "\n"); -      vty_out (vty, "\n"); - -      vty_out (vty, "LAN Prune Delay\n"); -      vty_out (vty, "---------------\n"); -      vty_out (vty, "Propagation Delay           : %d msec\n", -                pim_ifp->pim_propagation_delay_msec); -      vty_out (vty, "Propagation Delay (Highest) : %d msec\n", -                pim_ifp->pim_neighbors_highest_propagation_delay_msec); -      vty_out (vty, "Override Interval           : %d msec\n", -                pim_ifp->pim_override_interval_msec); -      vty_out (vty, "Override Interval (Highest) : %d msec\n", -                pim_ifp->pim_neighbors_highest_override_interval_msec); -      vty_out (vty, "\n"); -      vty_out (vty, "\n"); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } else { -    if (!found_ifname) -      vty_out (vty, "%% No such interface\n"); -  } +	struct listnode *node; +	struct interface *ifp; +	time_t now; + +	now = pim_time_monotonic_sec(); + +	vty_out(vty, +		"Interface Address         Source          Group           Socket Uptime  \n"); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		struct pim_interface *pim_ifp; +		struct listnode *join_node; +		struct igmp_join *ij; +		struct in_addr pri_addr; +		char pri_addr_str[INET_ADDRSTRLEN]; + +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (!pim_ifp->igmp_join_list) +			continue; + +		pri_addr = pim_find_primary_addr(ifp); +		pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, +			       sizeof(pri_addr_str)); + +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, +					  ij)) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			char uptime[10]; + +			pim_time_uptime(uptime, sizeof(uptime), +					now - ij->sock_creation); +			pim_inet4_dump("<grp?>", ij->group_addr, group_str, +				       sizeof(group_str)); +			pim_inet4_dump("<src?>", ij->source_addr, source_str, +				       sizeof(source_str)); + +			vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s\n", +				ifp->name, pri_addr_str, source_str, group_str, +				ij->sock_fd, uptime); +		} /* for (pim_ifp->igmp_join_list) */ + +	} /* for (iflist) */ +} + +static void pim_show_interfaces_single(struct vty *vty, const char *ifname, +				       u_char uj) +{ +	struct in_addr ifaddr; +	struct interface *ifp; +	struct listnode *neighnode; +	struct listnode *node; +	struct listnode *upnode; +	struct pim_interface *pim_ifp; +	struct pim_neighbor *neigh; +	struct pim_upstream *up; +	time_t now; +	char dr_str[INET_ADDRSTRLEN]; +	char dr_uptime[10]; +	char expire[10]; +	char grp_str[INET_ADDRSTRLEN]; +	char hello_period[10]; +	char hello_timer[10]; +	char neigh_src_str[INET_ADDRSTRLEN]; +	char src_str[INET_ADDRSTRLEN]; +	char stat_uptime[10]; +	char uptime[10]; +	int mloop; +	int found_ifname = 0; +	int print_header; +	json_object *json = NULL; +	json_object *json_row = NULL; +	json_object *json_pim_neighbor = NULL; +	json_object *json_pim_neighbors = NULL; +	json_object *json_group = NULL; +	json_object *json_group_source = NULL; +	json_object *json_fhr_sources = NULL; +	struct pim_secondary_addr *sec_addr; +	struct listnode *sec_node; + +	now = pim_time_monotonic_sec(); + +	if (uj) +		json = json_object_new_object(); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (pim_ifp->pim_sock_fd < 0) +			continue; + +		if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) +			continue; + +		found_ifname = 1; +		ifaddr = pim_ifp->primary_address; +		pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr, dr_str, +			       sizeof(dr_str)); +		pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, +				      pim_ifp->pim_dr_election_last); +		pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), +					 pim_ifp->t_pim_hello_timer); +		pim_time_mmss(hello_period, sizeof(hello_period), +			      pim_ifp->pim_hello_period); +		pim_time_uptime(stat_uptime, sizeof(stat_uptime), +				now - pim_ifp->pim_ifstat_start); +		mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); + +		if (uj) { +			char pbuf[PREFIX2STR_BUFFER]; +			json_row = json_object_new_object(); +			json_object_pim_ifp_add(json_row, ifp); + +			if (pim_ifp->update_source.s_addr != INADDR_ANY) { +				json_object_string_add( +					json_row, "useSource", +					inet_ntoa(pim_ifp->update_source)); +			} +			if (pim_ifp->sec_addr_list) { +				json_object *sec_list = NULL; + +				sec_list = json_object_new_array(); +				for (ALL_LIST_ELEMENTS_RO( +					     pim_ifp->sec_addr_list, sec_node, +					     sec_addr)) { +					json_object_array_add( +						sec_list, +						json_object_new_string( +							prefix2str( +								&sec_addr->addr, +								pbuf, +								sizeof(pbuf)))); +				} +				json_object_object_add(json_row, +						       "secondaryAddressList", +						       sec_list); +			} + +			// PIM neighbors +			if (pim_ifp->pim_neighbor_list->count) { +				json_pim_neighbors = json_object_new_object(); + +				for (ALL_LIST_ELEMENTS_RO( +					     pim_ifp->pim_neighbor_list, +					     neighnode, neigh)) { +					json_pim_neighbor = +						json_object_new_object(); +					pim_inet4_dump("<src?>", +						       neigh->source_addr, +						       neigh_src_str, +						       sizeof(neigh_src_str)); +					pim_time_uptime(uptime, sizeof(uptime), +							now - neigh->creation); +					pim_time_timer_to_hhmmss( +						expire, sizeof(expire), +						neigh->t_expire_timer); + +					json_object_string_add( +						json_pim_neighbor, "address", +						neigh_src_str); +					json_object_string_add( +						json_pim_neighbor, "upTime", +						uptime); +					json_object_string_add( +						json_pim_neighbor, "holdtime", +						expire); + +					json_object_object_add( +						json_pim_neighbors, +						neigh_src_str, +						json_pim_neighbor); +				} + +				json_object_object_add(json_row, "neighbors", +						       json_pim_neighbors); +			} + +			json_object_string_add(json_row, "drAddress", dr_str); +			json_object_int_add(json_row, "drPriority", +					    pim_ifp->pim_dr_priority); +			json_object_string_add(json_row, "drUptime", dr_uptime); +			json_object_int_add(json_row, "drElections", +					    pim_ifp->pim_dr_election_count); +			json_object_int_add(json_row, "drChanges", +					    pim_ifp->pim_dr_election_changes); + +			// FHR +			for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, +						  up)) { +				if (ifp == up->rpf.source_nexthop.interface) { +					if (up->flags +					    & PIM_UPSTREAM_FLAG_MASK_FHR) { +						if (!json_fhr_sources) { +							json_fhr_sources = +								json_object_new_object(); +						} + +						pim_inet4_dump("<src?>", +							       up->sg.src, +							       src_str, +							       sizeof(src_str)); +						pim_inet4_dump("<grp?>", +							       up->sg.grp, +							       grp_str, +							       sizeof(grp_str)); +						pim_time_uptime( +							uptime, sizeof(uptime), +							now - up->state_transition); + +						/* Does this group live in +						 * json_fhr_sources?  If not +						 * create it. */ +						json_object_object_get_ex( +							json_fhr_sources, +							grp_str, &json_group); + +						if (!json_group) { +							json_group = +								json_object_new_object(); +							json_object_object_add( +								json_fhr_sources, +								grp_str, +								json_group); +						} + +						json_group_source = +							json_object_new_object(); +						json_object_string_add( +							json_group_source, +							"source", src_str); +						json_object_string_add( +							json_group_source, +							"group", grp_str); +						json_object_string_add( +							json_group_source, +							"upTime", uptime); +						json_object_object_add( +							json_group, src_str, +							json_group_source); +					} +				} +			} + +			if (json_fhr_sources) { +				json_object_object_add(json_row, +						       "firstHopRouter", +						       json_fhr_sources); +			} + +			json_object_int_add(json_row, "helloPeriod", +					    pim_ifp->pim_hello_period); +			json_object_string_add(json_row, "helloTimer", +					       hello_timer); +			json_object_string_add(json_row, "helloStatStart", +					       stat_uptime); +			json_object_int_add(json_row, "helloReceived", +					    pim_ifp->pim_ifstat_hello_recv); +			json_object_int_add(json_row, "helloReceivedFailed", +					    pim_ifp->pim_ifstat_hello_recvfail); +			json_object_int_add(json_row, "helloSend", +					    pim_ifp->pim_ifstat_hello_sent); +			json_object_int_add(json_row, "hellosendFailed", +					    pim_ifp->pim_ifstat_hello_sendfail); +			json_object_int_add(json_row, "helloGenerationId", +					    pim_ifp->pim_generation_id); +			json_object_int_add(json_row, "flagMulticastLoop", +					    mloop); + +			json_object_int_add( +				json_row, "effectivePropagationDelay", +				pim_if_effective_propagation_delay_msec(ifp)); +			json_object_int_add( +				json_row, "effectiveOverrideInterval", +				pim_if_effective_override_interval_msec(ifp)); +			json_object_int_add( +				json_row, "joinPruneOverrideInterval", +				pim_if_jp_override_interval_msec(ifp)); + +			json_object_int_add( +				json_row, "propagationDelay", +				pim_ifp->pim_propagation_delay_msec); +			json_object_int_add( +				json_row, "propagationDelayHighest", +				pim_ifp->pim_neighbors_highest_propagation_delay_msec); +			json_object_int_add( +				json_row, "overrideInterval", +				pim_ifp->pim_override_interval_msec); +			json_object_int_add( +				json_row, "overrideIntervalHighest", +				pim_ifp->pim_neighbors_highest_override_interval_msec); +			json_object_object_add(json, ifp->name, json_row); + +		} else { +			vty_out(vty, "Interface  : %s\n", ifp->name); +			vty_out(vty, "State      : %s\n", +				if_is_up(ifp) ? "up" : "down"); +			if (pim_ifp->update_source.s_addr != INADDR_ANY) { +				vty_out(vty, "Use Source : %s\n", +					inet_ntoa(pim_ifp->update_source)); +			} +			if (pim_ifp->sec_addr_list) { +				char pbuf[PREFIX2STR_BUFFER]; +				vty_out(vty, "Address    : %s (primary)\n", +					inet_ntoa(ifaddr)); +				for (ALL_LIST_ELEMENTS_RO( +					     pim_ifp->sec_addr_list, sec_node, +					     sec_addr)) { +					vty_out(vty, "             %s\n", +						prefix2str(&sec_addr->addr, +							   pbuf, sizeof(pbuf))); +				} +			} else { +				vty_out(vty, "Address    : %s\n", +					inet_ntoa(ifaddr)); +			} +			vty_out(vty, "\n"); + +			// PIM neighbors +			print_header = 1; + +			for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, +						  neighnode, neigh)) { + +				if (print_header) { +					vty_out(vty, "PIM Neighbors\n"); +					vty_out(vty, "-------------\n"); +					print_header = 0; +				} + +				pim_inet4_dump("<src?>", neigh->source_addr, +					       neigh_src_str, +					       sizeof(neigh_src_str)); +				pim_time_uptime(uptime, sizeof(uptime), +						now - neigh->creation); +				pim_time_timer_to_hhmmss(expire, sizeof(expire), +							 neigh->t_expire_timer); +				vty_out(vty, +					"%-15s : up for %s, holdtime expires in %s\n", +					neigh_src_str, uptime, expire); +			} + +			if (!print_header) { +				vty_out(vty, "\n"); +				vty_out(vty, "\n"); +			} + +			vty_out(vty, "Designated Router\n"); +			vty_out(vty, "-----------------\n"); +			vty_out(vty, "Address   : %s\n", dr_str); +			vty_out(vty, "Priority  : %d\n", +				pim_ifp->pim_dr_priority); +			vty_out(vty, "Uptime    : %s\n", dr_uptime); +			vty_out(vty, "Elections : %d\n", +				pim_ifp->pim_dr_election_count); +			vty_out(vty, "Changes   : %d\n", +				pim_ifp->pim_dr_election_changes); +			vty_out(vty, "\n"); +			vty_out(vty, "\n"); + +			// FHR +			print_header = 1; +			for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, +						  up)) { +				if (strcmp(ifp->name, +					   up->rpf.source_nexthop +						   .interface->name) +				    == 0) { +					if (up->flags +					    & PIM_UPSTREAM_FLAG_MASK_FHR) { + +						if (print_header) { +							vty_out(vty, +								"FHR - First Hop Router\n"); +							vty_out(vty, +								"----------------------\n"); +							print_header = 0; +						} + +						pim_inet4_dump("<src?>", +							       up->sg.src, +							       src_str, +							       sizeof(src_str)); +						pim_inet4_dump("<grp?>", +							       up->sg.grp, +							       grp_str, +							       sizeof(grp_str)); +						pim_time_uptime( +							uptime, sizeof(uptime), +							now - up->state_transition); +						vty_out(vty, +							"%s : %s is a source, uptime is %s\n", +							grp_str, src_str, +							uptime); +					} +				} +			} + +			if (!print_header) { +				vty_out(vty, "\n"); +				vty_out(vty, "\n"); +			} + +			vty_out(vty, "Hellos\n"); +			vty_out(vty, "------\n"); +			vty_out(vty, "Period         : %d\n", +				pim_ifp->pim_hello_period); +			vty_out(vty, "Timer          : %s\n", hello_timer); +			vty_out(vty, "StatStart      : %s\n", stat_uptime); +			vty_out(vty, "Receive        : %d\n", +				pim_ifp->pim_ifstat_hello_recv); +			vty_out(vty, "Receive Failed : %d\n", +				pim_ifp->pim_ifstat_hello_recvfail); +			vty_out(vty, "Send           : %d\n", +				pim_ifp->pim_ifstat_hello_sent); +			vty_out(vty, "Send Failed    : %d\n", +				pim_ifp->pim_ifstat_hello_sendfail); +			vty_out(vty, "Generation ID  : %08x\n", +				pim_ifp->pim_generation_id); +			vty_out(vty, "\n"); +			vty_out(vty, "\n"); + +			pim_print_ifp_flags(vty, ifp, mloop); + +			vty_out(vty, "Join Prune Interval\n"); +			vty_out(vty, "-------------------\n"); +			vty_out(vty, "LAN Delay                    : %s\n", +				pim_if_lan_delay_enabled(ifp) ? "yes" : "no"); +			vty_out(vty, "Effective Propagation Delay  : %d msec\n", +				pim_if_effective_propagation_delay_msec(ifp)); +			vty_out(vty, "Effective Override Interval  : %d msec\n", +				pim_if_effective_override_interval_msec(ifp)); +			vty_out(vty, "Join Prune Override Interval : %d msec\n", +				pim_if_jp_override_interval_msec(ifp)); +			vty_out(vty, "\n"); +			vty_out(vty, "\n"); + +			vty_out(vty, "LAN Prune Delay\n"); +			vty_out(vty, "---------------\n"); +			vty_out(vty, "Propagation Delay           : %d msec\n", +				pim_ifp->pim_propagation_delay_msec); +			vty_out(vty, "Propagation Delay (Highest) : %d msec\n", +				pim_ifp->pim_neighbors_highest_propagation_delay_msec); +			vty_out(vty, "Override Interval           : %d msec\n", +				pim_ifp->pim_override_interval_msec); +			vty_out(vty, "Override Interval (Highest) : %d msec\n", +				pim_ifp->pim_neighbors_highest_override_interval_msec); +			vty_out(vty, "\n"); +			vty_out(vty, "\n"); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} else { +		if (!found_ifname) +			vty_out(vty, "%% No such interface\n"); +	}  }  static void pim_show_interfaces(struct vty *vty, u_char uj)  { -  struct interface *ifp; -  struct listnode *node; -  struct listnode *upnode; -  struct pim_interface *pim_ifp; -  struct pim_upstream *up; -  int fhr = 0; -  int pim_nbrs = 0; -  int pim_ifchannels = 0; -  json_object *json = NULL; -  json_object *json_row = NULL; -  json_object *json_tmp; - -  json = json_object_new_object(); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    pim_ifp = ifp->info; -     -    if (!pim_ifp) -      continue; - -    if (pim_ifp->pim_sock_fd < 0) -      continue; - -    pim_nbrs = pim_ifp->pim_neighbor_list->count; -    pim_ifchannels = pim_ifp->pim_ifchannel_list->count; -    fhr = 0; - -    for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) -      if (ifp ==  up->rpf.source_nexthop.interface) -        if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) -          fhr++; - -    json_row = json_object_new_object(); -    json_object_pim_ifp_add(json_row, ifp); -    json_object_int_add(json_row, "pimNeighbors", pim_nbrs); -    json_object_int_add(json_row, "pimIfChannels", pim_ifchannels); -    json_object_int_add(json_row, "firstHopRouter", fhr); -    json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); - -    if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) -      json_object_boolean_true_add(json_row, "pimDesignatedRouterLocal"); - -    json_object_object_add(json, ifp->name, json_row); -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -  } else { -    vty_out (vty, -              "Interface  State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n"); - -    json_object_object_foreach(json, key, val) { -      vty_out(vty, "%-9s  ", key); - -      json_object_object_get_ex(val, "state", &json_tmp); -      vty_out(vty, "%5s  ", json_object_get_string(json_tmp)); - -      json_object_object_get_ex(val, "address", &json_tmp); -      vty_out(vty, "%15s  ", json_object_get_string(json_tmp)); - -      json_object_object_get_ex(val, "pimNeighbors", &json_tmp); -      vty_out(vty, "%8d  ", json_object_get_int(json_tmp)); - -      if (json_object_object_get_ex(val, "pimDesignatedRouterLocal", &json_tmp)) { -        vty_out(vty, "%15s  ", "local"); -      } else { -        json_object_object_get_ex(val, "pimDesignatedRouter", &json_tmp); -        vty_out(vty, "%15s  ", json_object_get_string(json_tmp)); -      } - -      json_object_object_get_ex(val, "firstHopRouter", &json_tmp); -      vty_out(vty, "%3d  ", json_object_get_int(json_tmp)); - -      json_object_object_get_ex(val, "pimIfChannels", &json_tmp); -      vty_out (vty, "%9d\n", json_object_get_int(json_tmp)); -    } -  } - -  json_object_free(json); -} - -static void pim_show_interface_traffic (struct vty *vty, u_char uj) -{ -  struct interface *ifp = NULL; -  struct pim_interface *pim_ifp = NULL; -  struct listnode *node = NULL; -  json_object *json = NULL; -  json_object *json_row = NULL; - -  if (uj) -    json = json_object_new_object (); -  else -    { -      vty_out (vty, "\n"); -      vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", -               "    HELLO", "    JOIN", "   PRUNE", "   REGISTER", -               "  REGISTER-STOP", "  ASSERT"); -      vty_out (vty, -               "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", -               "", "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx", -               "     Rx/Tx", "    Rx/Tx"); -      vty_out (vty, -           "---------------------------------------------------------------------------------------------------------------\n"); -    } - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) -    { -      pim_ifp = ifp->info; - -      if (!pim_ifp) -        continue; - -      if (pim_ifp->pim_sock_fd < 0) -        continue; -      if (uj) -        { -          json_row = json_object_new_object (); -          json_object_pim_ifp_add (json_row, ifp); -          json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); -          json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); -          json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); -          json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); -          json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); -          json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); -          json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); -          json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); -          json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); -          json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); - -          json_object_object_add (json, ifp->name, json_row); -        } -      else -        { -          vty_out (vty, -               "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", -               ifp->name, pim_ifp->pim_ifstat_hello_recv, -               pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, -               pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, -               pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, -               pim_ifp->pim_ifstat_reg_send, -               pim_ifp->pim_ifstat_reg_stop_recv, -               pim_ifp->pim_ifstat_reg_stop_send, -               pim_ifp->pim_ifstat_assert_recv, -               pim_ifp->pim_ifstat_assert_send); -        } -    } -  if (uj) -    { -      vty_out (vty, "%s\n", -                 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -      json_object_free (json); -    } -} - -static void pim_show_interface_traffic_single (struct vty *vty, const char *ifname, u_char uj) -{ -  struct interface *ifp = NULL; -  struct pim_interface *pim_ifp = NULL; -  struct listnode *node = NULL; -  json_object *json = NULL; -  json_object *json_row = NULL; -  uint8_t found_ifname = 0; - -  if (uj) -    json = json_object_new_object (); -  else -    { -      vty_out (vty, "\n"); -      vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", -               "    HELLO", "    JOIN", "   PRUNE", "   REGISTER", -               "  REGISTER-STOP", "  ASSERT"); -      vty_out (vty, -               "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", -               "", "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx", -               "     Rx/Tx", "    Rx/Tx"); -      vty_out (vty, -           "---------------------------------------------------------------------------------------------------------------\n"); -    } - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) -    { -      if (strcmp (ifname, ifp->name)) -        continue; - -      pim_ifp = ifp->info; - -      if (!pim_ifp) -        continue; - -      if (pim_ifp->pim_sock_fd < 0) -        continue; - -      found_ifname = 1; -      if (uj) -        { -          json_row = json_object_new_object (); -          json_object_pim_ifp_add (json_row, ifp); -          json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); -          json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); -          json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); -          json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); -          json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); -          json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); -          json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); -          json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); -          json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); -          json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); - -          json_object_object_add (json, ifp->name, json_row); -        } -      else -        { -          vty_out (vty, -               "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", -               ifp->name, pim_ifp->pim_ifstat_hello_recv, -               pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, -               pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, -               pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, -               pim_ifp->pim_ifstat_reg_send, -               pim_ifp->pim_ifstat_reg_stop_recv, -               pim_ifp->pim_ifstat_reg_stop_send, -               pim_ifp->pim_ifstat_assert_recv, -               pim_ifp->pim_ifstat_assert_send); -        } -    } -  if (uj) -    { -      vty_out (vty, "%s\n", -                 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -      json_object_free (json); -    } -  else -    { -      if (!found_ifname) -        vty_out (vty, "%% No such interface\n"); -    } +	struct interface *ifp; +	struct listnode *node; +	struct listnode *upnode; +	struct pim_interface *pim_ifp; +	struct pim_upstream *up; +	int fhr = 0; +	int pim_nbrs = 0; +	int pim_ifchannels = 0; +	json_object *json = NULL; +	json_object *json_row = NULL; +	json_object *json_tmp; + +	json = json_object_new_object(); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (pim_ifp->pim_sock_fd < 0) +			continue; + +		pim_nbrs = pim_ifp->pim_neighbor_list->count; +		pim_ifchannels = pim_ifp->pim_ifchannel_list->count; +		fhr = 0; + +		for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) +			if (ifp == up->rpf.source_nexthop.interface) +				if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) +					fhr++; + +		json_row = json_object_new_object(); +		json_object_pim_ifp_add(json_row, ifp); +		json_object_int_add(json_row, "pimNeighbors", pim_nbrs); +		json_object_int_add(json_row, "pimIfChannels", pim_ifchannels); +		json_object_int_add(json_row, "firstHopRouter", fhr); +		json_object_string_add(json_row, "pimDesignatedRouter", +				       inet_ntoa(pim_ifp->pim_dr_addr)); + +		if (pim_ifp->pim_dr_addr.s_addr +		    == pim_ifp->primary_address.s_addr) +			json_object_boolean_true_add( +				json_row, "pimDesignatedRouterLocal"); + +		json_object_object_add(json, ifp->name, json_row); +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +	} else { +		vty_out(vty, +			"Interface  State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n"); + +		json_object_object_foreach(json, key, val) +		{ +			vty_out(vty, "%-9s  ", key); + +			json_object_object_get_ex(val, "state", &json_tmp); +			vty_out(vty, "%5s  ", json_object_get_string(json_tmp)); + +			json_object_object_get_ex(val, "address", &json_tmp); +			vty_out(vty, "%15s  ", +				json_object_get_string(json_tmp)); + +			json_object_object_get_ex(val, "pimNeighbors", +						  &json_tmp); +			vty_out(vty, "%8d  ", json_object_get_int(json_tmp)); + +			if (json_object_object_get_ex( +				    val, "pimDesignatedRouterLocal", +				    &json_tmp)) { +				vty_out(vty, "%15s  ", "local"); +			} else { +				json_object_object_get_ex( +					val, "pimDesignatedRouter", &json_tmp); +				vty_out(vty, "%15s  ", +					json_object_get_string(json_tmp)); +			} + +			json_object_object_get_ex(val, "firstHopRouter", +						  &json_tmp); +			vty_out(vty, "%3d  ", json_object_get_int(json_tmp)); + +			json_object_object_get_ex(val, "pimIfChannels", +						  &json_tmp); +			vty_out(vty, "%9d\n", json_object_get_int(json_tmp)); +		} +	} + +	json_object_free(json); +} + +static void pim_show_interface_traffic(struct vty *vty, u_char uj) +{ +	struct interface *ifp = NULL; +	struct pim_interface *pim_ifp = NULL; +	struct listnode *node = NULL; +	json_object *json = NULL; +	json_object *json_row = NULL; + +	if (uj) +		json = json_object_new_object(); +	else { +		vty_out(vty, "\n"); +		vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", +			"Interface", "    HELLO", "    JOIN", "   PRUNE", +			"   REGISTER", "  REGISTER-STOP", "  ASSERT"); +		vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "", +			"      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx", +			"     Rx/Tx", "    Rx/Tx"); +		vty_out(vty, +			"---------------------------------------------------------------------------------------------------------------\n"); +	} + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (pim_ifp->pim_sock_fd < 0) +			continue; +		if (uj) { +			json_row = json_object_new_object(); +			json_object_pim_ifp_add(json_row, ifp); +			json_object_int_add(json_row, "helloRx", +					    pim_ifp->pim_ifstat_hello_recv); +			json_object_int_add(json_row, "helloTx", +					    pim_ifp->pim_ifstat_hello_sent); +			json_object_int_add(json_row, "joinRx", +					    pim_ifp->pim_ifstat_join_recv); +			json_object_int_add(json_row, "joinTx", +					    pim_ifp->pim_ifstat_join_send); +			json_object_int_add(json_row, "registerRx", +					    pim_ifp->pim_ifstat_reg_recv); +			json_object_int_add(json_row, "registerTx", +					    pim_ifp->pim_ifstat_reg_recv); +			json_object_int_add(json_row, "registerStopRx", +					    pim_ifp->pim_ifstat_reg_stop_recv); +			json_object_int_add(json_row, "registerStopTx", +					    pim_ifp->pim_ifstat_reg_stop_send); +			json_object_int_add(json_row, "assertRx", +					    pim_ifp->pim_ifstat_assert_recv); +			json_object_int_add(json_row, "assertTx", +					    pim_ifp->pim_ifstat_assert_send); + +			json_object_object_add(json, ifp->name, json_row); +		} else { +			vty_out(vty, +				"%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", +				ifp->name, pim_ifp->pim_ifstat_hello_recv, +				pim_ifp->pim_ifstat_hello_sent, +				pim_ifp->pim_ifstat_join_recv, +				pim_ifp->pim_ifstat_join_send, +				pim_ifp->pim_ifstat_prune_recv, +				pim_ifp->pim_ifstat_prune_send, +				pim_ifp->pim_ifstat_reg_recv, +				pim_ifp->pim_ifstat_reg_send, +				pim_ifp->pim_ifstat_reg_stop_recv, +				pim_ifp->pim_ifstat_reg_stop_send, +				pim_ifp->pim_ifstat_assert_recv, +				pim_ifp->pim_ifstat_assert_send); +		} +	} +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} +} + +static void pim_show_interface_traffic_single(struct vty *vty, +					      const char *ifname, u_char uj) +{ +	struct interface *ifp = NULL; +	struct pim_interface *pim_ifp = NULL; +	struct listnode *node = NULL; +	json_object *json = NULL; +	json_object *json_row = NULL; +	uint8_t found_ifname = 0; + +	if (uj) +		json = json_object_new_object(); +	else { +		vty_out(vty, "\n"); +		vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", +			"Interface", "    HELLO", "    JOIN", "   PRUNE", +			"   REGISTER", "  REGISTER-STOP", "  ASSERT"); +		vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "", +			"      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx", +			"     Rx/Tx", "    Rx/Tx"); +		vty_out(vty, +			"---------------------------------------------------------------------------------------------------------------\n"); +	} + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		if (strcmp(ifname, ifp->name)) +			continue; + +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (pim_ifp->pim_sock_fd < 0) +			continue; + +		found_ifname = 1; +		if (uj) { +			json_row = json_object_new_object(); +			json_object_pim_ifp_add(json_row, ifp); +			json_object_int_add(json_row, "helloRx", +					    pim_ifp->pim_ifstat_hello_recv); +			json_object_int_add(json_row, "helloTx", +					    pim_ifp->pim_ifstat_hello_sent); +			json_object_int_add(json_row, "joinRx", +					    pim_ifp->pim_ifstat_join_recv); +			json_object_int_add(json_row, "joinTx", +					    pim_ifp->pim_ifstat_join_send); +			json_object_int_add(json_row, "registerRx", +					    pim_ifp->pim_ifstat_reg_recv); +			json_object_int_add(json_row, "registerTx", +					    pim_ifp->pim_ifstat_reg_recv); +			json_object_int_add(json_row, "registerStopRx", +					    pim_ifp->pim_ifstat_reg_stop_recv); +			json_object_int_add(json_row, "registerStopTx", +					    pim_ifp->pim_ifstat_reg_stop_send); +			json_object_int_add(json_row, "assertRx", +					    pim_ifp->pim_ifstat_assert_recv); +			json_object_int_add(json_row, "assertTx", +					    pim_ifp->pim_ifstat_assert_send); + +			json_object_object_add(json, ifp->name, json_row); +		} else { +			vty_out(vty, +				"%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", +				ifp->name, pim_ifp->pim_ifstat_hello_recv, +				pim_ifp->pim_ifstat_hello_sent, +				pim_ifp->pim_ifstat_join_recv, +				pim_ifp->pim_ifstat_join_send, +				pim_ifp->pim_ifstat_prune_recv, +				pim_ifp->pim_ifstat_prune_send, +				pim_ifp->pim_ifstat_reg_recv, +				pim_ifp->pim_ifstat_reg_send, +				pim_ifp->pim_ifstat_reg_stop_recv, +				pim_ifp->pim_ifstat_reg_stop_send, +				pim_ifp->pim_ifstat_assert_recv, +				pim_ifp->pim_ifstat_assert_send); +		} +	} +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} else { +		if (!found_ifname) +			vty_out(vty, "%% No such interface\n"); +	}  }  static void pim_show_join(struct vty *vty, u_char uj)  { -  struct pim_interface *pim_ifp; -  struct in_addr ifaddr; -  struct listnode *ch_node; -  struct pim_ifchannel *ch; -  time_t            now; -  json_object *json = NULL; -  json_object *json_iface = NULL; -  json_object *json_row = NULL; -  json_object *json_grp = NULL; -   -  now = pim_time_monotonic_sec(); - -  if (uj) -    json = json_object_new_object(); -  else -    vty_out (vty, -            "Interface Address         Source          Group           State  Uptime   Expire Prune\n"); - -  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - -    pim_ifp = ch->interface->info; -     -    if (!pim_ifp) -      continue; - -    ifaddr = pim_ifp->primary_address; - -    char ch_src_str[INET_ADDRSTRLEN]; -    char ch_grp_str[INET_ADDRSTRLEN]; -    char uptime[10]; -    char expire[10]; -    char prune[10]; - -    pim_inet4_dump("<ch_src?>", ch->sg.src, -		   ch_src_str, sizeof(ch_src_str)); -    pim_inet4_dump("<ch_grp?>", ch->sg.grp, -		   ch_grp_str, sizeof(ch_grp_str)); - -    pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); -    pim_time_timer_to_mmss(expire, sizeof(expire), -			   ch->t_ifjoin_expiry_timer); -    pim_time_timer_to_mmss(prune, sizeof(prune), -			   ch->t_ifjoin_prune_pending_timer); - -    if (uj) { -      json_object_object_get_ex(json, ch->interface->name, &json_iface); - -      if (!json_iface) { -	json_iface = json_object_new_object(); -	json_object_pim_ifp_add(json_iface, ch->interface); -	json_object_object_add(json, ch->interface->name, json_iface); -      } - -      json_row = json_object_new_object(); -      json_object_string_add(json_row, "source", ch_src_str); -      json_object_string_add(json_row, "group", ch_grp_str); -      json_object_string_add(json_row, "upTime", uptime); -      json_object_string_add(json_row, "expire", expire); -      json_object_string_add(json_row, "prune", prune); -      json_object_string_add(json_row, "channelJoinName", -                             pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); -      if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) -        json_object_int_add(json_row, "SGRpt", 1); - -      json_object_object_get_ex(json_iface, ch_grp_str, &json_grp); -      if (!json_grp) -        { -          json_grp = json_object_new_object(); -          json_object_object_add(json_grp, ch_src_str, json_row); -          json_object_object_add(json_iface, ch_grp_str, json_grp); -        } -      else -        json_object_object_add(json_grp, ch_src_str, json_row); -    } else { -      vty_out (vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", -	      ch->interface->name, -	      inet_ntoa(ifaddr), -	      ch_src_str, -	      ch_grp_str, -	      pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), -	      uptime, -	      expire, -	      prune); -    } -  } /* scan interface channels */ - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } -} - -static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_char uj) -{ -  struct listnode  *node; -  struct listnode *neighnode; -  struct interface *ifp; -  struct pim_interface *pim_ifp; -  struct pim_neighbor *neigh; -  time_t            now; -  int found_neighbor = 0; -  int option_address_list; -  int option_dr_priority; -  int option_generation_id; -  int option_holdtime; -  int option_lan_prune_delay; -  int option_t_bit; -  char uptime[10]; -  char expire[10]; -  char neigh_src_str[INET_ADDRSTRLEN]; - -  json_object *json = NULL; -  json_object *json_ifp = NULL; -  json_object *json_row = NULL; - -  now = pim_time_monotonic_sec(); - -  if (uj) -    json = json_object_new_object(); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    pim_ifp = ifp->info; - -    if (!pim_ifp) -      continue; - -    if (pim_ifp->pim_sock_fd < 0) -      continue; - -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { -      pim_inet4_dump("<src?>", neigh->source_addr, -		     neigh_src_str, sizeof(neigh_src_str)); - -      /* -       * The user can specify either the interface name or the PIM neighbor IP. -       * If this pim_ifp matches neither then skip. -       */ -      if (strcmp(neighbor, "detail") && -          strcmp(neighbor, ifp->name) && -          strcmp(neighbor, neigh_src_str)) -        continue; - -      found_neighbor = 1; -      pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); -      pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - -      option_address_list = 0; -      option_dr_priority = 0; -      option_generation_id = 0; -      option_holdtime = 0; -      option_lan_prune_delay = 0; -      option_t_bit = 0; - -      if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST)) -        option_address_list = 1; - -      if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)) -        option_dr_priority = 1; - -      if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID)) -        option_generation_id = 1; - -      if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME)) -        option_holdtime = 1; - -      if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY)) -        option_lan_prune_delay = 1; - -      if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) -        option_t_bit = 1; - -      if (uj) { - -        /* Does this ifp live in json?  If not create it. */ -        json_object_object_get_ex(json, ifp->name, &json_ifp); - -        if (!json_ifp) { -          json_ifp = json_object_new_object(); -          json_object_pim_ifp_add(json_ifp, ifp); -          json_object_object_add(json, ifp->name, json_ifp); -        } - -        json_row = json_object_new_object(); -        json_object_string_add(json_row, "interface", ifp->name); -        json_object_string_add(json_row, "address", neigh_src_str); -        json_object_string_add(json_row, "upTime", uptime); -        json_object_string_add(json_row, "holdtime", expire); -        json_object_int_add(json_row, "drPriority", neigh->dr_priority); -        json_object_int_add(json_row, "generationId", neigh->generation_id); - -        if (option_address_list) -          json_object_boolean_true_add(json_row, "helloOptionAddressList"); - -        if (option_dr_priority) -          json_object_boolean_true_add(json_row, "helloOptionDrPriority"); - -        if (option_generation_id) -          json_object_boolean_true_add(json_row, "helloOptionGenerationId"); - -        if (option_holdtime) -          json_object_boolean_true_add(json_row, "helloOptionHoldtime"); - -        if (option_lan_prune_delay) -          json_object_boolean_true_add(json_row, "helloOptionLanPruneDelay"); - -        if (option_t_bit) -          json_object_boolean_true_add(json_row, "helloOptionTBit"); - -        json_object_object_add(json_ifp, neigh_src_str, json_row); - -      } else { -        vty_out (vty, "Interface : %s\n", ifp->name); -        vty_out (vty, "Neighbor  : %s\n", neigh_src_str); -        vty_out (vty, "    Uptime                         : %s\n", uptime); -        vty_out (vty, "    Holdtime                       : %s\n", expire); -        vty_out (vty, "    DR Priority                    : %d\n", -                  neigh->dr_priority); -        vty_out (vty, "    Generation ID                  : %08x\n", -                  neigh->generation_id); -        vty_out (vty, "    Override Interval (msec)       : %d\n", -                  neigh->override_interval_msec); -        vty_out (vty, "    Propagation Delay (msec)       : %d\n", -                  neigh->propagation_delay_msec); -        vty_out (vty, "    Hello Option - Address List    : %s\n", -                  option_address_list ? "yes" : "no"); -        vty_out (vty, "    Hello Option - DR Priority     : %s\n", -                  option_dr_priority ? "yes" : "no"); -        vty_out (vty, "    Hello Option - Generation ID   : %s\n", -                  option_generation_id ? "yes" : "no"); -        vty_out (vty, "    Hello Option - Holdtime        : %s\n", -                  option_holdtime ? "yes" : "no"); -        vty_out (vty, "    Hello Option - LAN Prune Delay : %s\n", -                  option_lan_prune_delay ? "yes" : "no"); -        vty_out (vty, "    Hello Option - T-bit           : %s\n", -                  option_t_bit ? "yes" : "no"); -        pim_bfd_show_info (vty, neigh->bfd_info, json_ifp, uj, 0); -        vty_out (vty, "\n"); -      } -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } else { -    { -      if (!found_neighbor) -        vty_out (vty, "%% No such interface or neighbor\n"); -    } -  } -} - -static void -pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_char uj) -{ -  struct channel_oil *c_oil; -  struct listnode *node; -  json_object *json = NULL; -  json_object *json_group = NULL; -  json_object *json_ifp_in = NULL; -  json_object *json_ifp_out = NULL; -  json_object *json_source = NULL; -  time_t now; -  int first_oif; -  now = pim_time_monotonic_sec(); - -  if (uj) { -    json = json_object_new_object(); -  } else { -    vty_out(vty, "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); -    vty_out (vty, "\nInstalled Source           Group            IIF      OIL\n"); -  } - -  for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { -    char grp_str[INET_ADDRSTRLEN]; -    char src_str[INET_ADDRSTRLEN]; -    char in_ifname[INTERFACE_NAMSIZ+1]; -    char out_ifname[INTERFACE_NAMSIZ+1]; -    int oif_vif_index; -    struct interface *ifp_in; -    first_oif = 1; - -    pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); -    pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); -    ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - -    if (ifp_in) -      strcpy(in_ifname, ifp_in->name); -    else -      strcpy(in_ifname, "<iif?>"); - -    if (src_or_group) -      { -        if (strcmp(src_or_group, src_str) && strcmp(src_or_group, grp_str)) -          continue; - -        if (group && strcmp(group, grp_str)) -          continue; -      } - -    if (uj) { - -      /* Find the group, create it if it doesn't exist */ -      json_object_object_get_ex(json, grp_str, &json_group); - -      if (!json_group) { -        json_group = json_object_new_object(); -        json_object_object_add(json, grp_str, json_group); -      } - -      /* Find the source nested under the group, create it if it doesn't exist */ -      json_object_object_get_ex(json_group, src_str, &json_source); - -      if (!json_source) { -        json_source = json_object_new_object(); -        json_object_object_add(json_group, src_str, json_source); -      } - -      /* Find the inbound interface nested under the source, create it if it doesn't exist */ -      json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); - -      if (!json_ifp_in) { -        json_ifp_in = json_object_new_object(); -        json_object_object_add(json_source, in_ifname, json_ifp_in); -        json_object_int_add (json_source, "Installed", c_oil->installed); -        json_object_int_add (json_source, "RefCount", c_oil->oil_ref_count); -        json_object_int_add (json_source, "OilListSize", c_oil->oil_size); -        json_object_int_add (json_source, "OilRescan", c_oil->oil_inherited_rescan); -        json_object_int_add (json_source, "LastUsed", c_oil->cc.lastused); -        json_object_int_add (json_source, "PacketCount", c_oil->cc.pktcnt); -        json_object_int_add (json_source, "ByteCount", c_oil->cc.bytecnt); -        json_object_int_add (json_source, "WrongInterface", c_oil->cc.wrong_if); -      } -    } else { -        vty_out(vty, "%-9d %-15s  %-15s  %-7s  ", -                c_oil->installed, -                src_str, -                grp_str, -                ifp_in->name); -    } - -    for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { -      struct interface *ifp_out; -      char oif_uptime[10]; -      int ttl; - -      ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; -      if (ttl < 1) -        continue; - -      ifp_out = pim_if_find_by_vif_index(oif_vif_index); -      pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); - -      if (ifp_out) -        strcpy(out_ifname, ifp_out->name); -      else -        strcpy(out_ifname, "<oif?>"); - -      if (uj) { -        json_ifp_out = json_object_new_object(); -        json_object_string_add(json_ifp_out, "source", src_str); -        json_object_string_add(json_ifp_out, "group", grp_str); -        json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); -        json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); -        json_object_int_add(json_ifp_out, "installed", c_oil->installed); - -        json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); -      } else { -        if (first_oif) -          { -            first_oif = 0; -            vty_out(vty, "%s(%c%c%c%c)", out_ifname, -                    (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', -                    (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', -                    (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', -                    (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' '); -          } -        else -          vty_out(vty, ", %s(%c%c%c%c)", out_ifname, -                  (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', -                  (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', -                  (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', -                  (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ' ); -      } -    } - -    if (!uj) -      vty_out (vty, "\n"); -  } - - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } else { -    vty_out (vty, "\n"); -  } +	struct pim_interface *pim_ifp; +	struct in_addr ifaddr; +	struct listnode *ch_node; +	struct pim_ifchannel *ch; +	time_t now; +	json_object *json = NULL; +	json_object *json_iface = NULL; +	json_object *json_row = NULL; +	json_object *json_grp = NULL; + +	now = pim_time_monotonic_sec(); + +	if (uj) +		json = json_object_new_object(); +	else +		vty_out(vty, +			"Interface Address         Source          Group           State  Uptime   Expire Prune\n"); + +	for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + +		pim_ifp = ch->interface->info; + +		if (!pim_ifp) +			continue; + +		ifaddr = pim_ifp->primary_address; + +		char ch_src_str[INET_ADDRSTRLEN]; +		char ch_grp_str[INET_ADDRSTRLEN]; +		char uptime[10]; +		char expire[10]; +		char prune[10]; + +		pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, +			       sizeof(ch_src_str)); +		pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, +			       sizeof(ch_grp_str)); + +		pim_time_uptime_begin(uptime, sizeof(uptime), now, +				      ch->ifjoin_creation); +		pim_time_timer_to_mmss(expire, sizeof(expire), +				       ch->t_ifjoin_expiry_timer); +		pim_time_timer_to_mmss(prune, sizeof(prune), +				       ch->t_ifjoin_prune_pending_timer); + +		if (uj) { +			json_object_object_get_ex(json, ch->interface->name, +						  &json_iface); + +			if (!json_iface) { +				json_iface = json_object_new_object(); +				json_object_pim_ifp_add(json_iface, +							ch->interface); +				json_object_object_add( +					json, ch->interface->name, json_iface); +			} + +			json_row = json_object_new_object(); +			json_object_string_add(json_row, "source", ch_src_str); +			json_object_string_add(json_row, "group", ch_grp_str); +			json_object_string_add(json_row, "upTime", uptime); +			json_object_string_add(json_row, "expire", expire); +			json_object_string_add(json_row, "prune", prune); +			json_object_string_add( +				json_row, "channelJoinName", +				pim_ifchannel_ifjoin_name(ch->ifjoin_state, +							  ch->flags)); +			if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) +				json_object_int_add(json_row, "SGRpt", 1); + +			json_object_object_get_ex(json_iface, ch_grp_str, +						  &json_grp); +			if (!json_grp) { +				json_grp = json_object_new_object(); +				json_object_object_add(json_grp, ch_src_str, +						       json_row); +				json_object_object_add(json_iface, ch_grp_str, +						       json_grp); +			} else +				json_object_object_add(json_grp, ch_src_str, +						       json_row); +		} else { +			vty_out(vty, +				"%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", +				ch->interface->name, inet_ntoa(ifaddr), +				ch_src_str, ch_grp_str, +				pim_ifchannel_ifjoin_name(ch->ifjoin_state, +							  ch->flags), +				uptime, expire, prune); +		} +	} /* scan interface channels */ + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} +} + +static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, +				      u_char uj) +{ +	struct listnode *node; +	struct listnode *neighnode; +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	struct pim_neighbor *neigh; +	time_t now; +	int found_neighbor = 0; +	int option_address_list; +	int option_dr_priority; +	int option_generation_id; +	int option_holdtime; +	int option_lan_prune_delay; +	int option_t_bit; +	char uptime[10]; +	char expire[10]; +	char neigh_src_str[INET_ADDRSTRLEN]; + +	json_object *json = NULL; +	json_object *json_ifp = NULL; +	json_object *json_row = NULL; + +	now = pim_time_monotonic_sec(); + +	if (uj) +		json = json_object_new_object(); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (pim_ifp->pim_sock_fd < 0) +			continue; + +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, +					  neigh)) { +			pim_inet4_dump("<src?>", neigh->source_addr, +				       neigh_src_str, sizeof(neigh_src_str)); + +			/* +			 * The user can specify either the interface name or the +			 * PIM neighbor IP. +			 * If this pim_ifp matches neither then skip. +			 */ +			if (strcmp(neighbor, "detail") +			    && strcmp(neighbor, ifp->name) +			    && strcmp(neighbor, neigh_src_str)) +				continue; + +			found_neighbor = 1; +			pim_time_uptime(uptime, sizeof(uptime), +					now - neigh->creation); +			pim_time_timer_to_hhmmss(expire, sizeof(expire), +						 neigh->t_expire_timer); + +			option_address_list = 0; +			option_dr_priority = 0; +			option_generation_id = 0; +			option_holdtime = 0; +			option_lan_prune_delay = 0; +			option_t_bit = 0; + +			if (PIM_OPTION_IS_SET(neigh->hello_options, +					      PIM_OPTION_MASK_ADDRESS_LIST)) +				option_address_list = 1; + +			if (PIM_OPTION_IS_SET(neigh->hello_options, +					      PIM_OPTION_MASK_DR_PRIORITY)) +				option_dr_priority = 1; + +			if (PIM_OPTION_IS_SET(neigh->hello_options, +					      PIM_OPTION_MASK_GENERATION_ID)) +				option_generation_id = 1; + +			if (PIM_OPTION_IS_SET(neigh->hello_options, +					      PIM_OPTION_MASK_HOLDTIME)) +				option_holdtime = 1; + +			if (PIM_OPTION_IS_SET(neigh->hello_options, +					      PIM_OPTION_MASK_LAN_PRUNE_DELAY)) +				option_lan_prune_delay = 1; + +			if (PIM_OPTION_IS_SET( +				    neigh->hello_options, +				    PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) +				option_t_bit = 1; + +			if (uj) { + +				/* Does this ifp live in json?  If not create +				 * it. */ +				json_object_object_get_ex(json, ifp->name, +							  &json_ifp); + +				if (!json_ifp) { +					json_ifp = json_object_new_object(); +					json_object_pim_ifp_add(json_ifp, ifp); +					json_object_object_add(json, ifp->name, +							       json_ifp); +				} + +				json_row = json_object_new_object(); +				json_object_string_add(json_row, "interface", +						       ifp->name); +				json_object_string_add(json_row, "address", +						       neigh_src_str); +				json_object_string_add(json_row, "upTime", +						       uptime); +				json_object_string_add(json_row, "holdtime", +						       expire); +				json_object_int_add(json_row, "drPriority", +						    neigh->dr_priority); +				json_object_int_add(json_row, "generationId", +						    neigh->generation_id); + +				if (option_address_list) +					json_object_boolean_true_add( +						json_row, +						"helloOptionAddressList"); + +				if (option_dr_priority) +					json_object_boolean_true_add( +						json_row, +						"helloOptionDrPriority"); + +				if (option_generation_id) +					json_object_boolean_true_add( +						json_row, +						"helloOptionGenerationId"); + +				if (option_holdtime) +					json_object_boolean_true_add( +						json_row, +						"helloOptionHoldtime"); + +				if (option_lan_prune_delay) +					json_object_boolean_true_add( +						json_row, +						"helloOptionLanPruneDelay"); + +				if (option_t_bit) +					json_object_boolean_true_add( +						json_row, "helloOptionTBit"); + +				json_object_object_add(json_ifp, neigh_src_str, +						       json_row); + +			} else { +				vty_out(vty, "Interface : %s\n", ifp->name); +				vty_out(vty, "Neighbor  : %s\n", neigh_src_str); +				vty_out(vty, +					"    Uptime                         : %s\n", +					uptime); +				vty_out(vty, +					"    Holdtime                       : %s\n", +					expire); +				vty_out(vty, +					"    DR Priority                    : %d\n", +					neigh->dr_priority); +				vty_out(vty, +					"    Generation ID                  : %08x\n", +					neigh->generation_id); +				vty_out(vty, +					"    Override Interval (msec)       : %d\n", +					neigh->override_interval_msec); +				vty_out(vty, +					"    Propagation Delay (msec)       : %d\n", +					neigh->propagation_delay_msec); +				vty_out(vty, +					"    Hello Option - Address List    : %s\n", +					option_address_list ? "yes" : "no"); +				vty_out(vty, +					"    Hello Option - DR Priority     : %s\n", +					option_dr_priority ? "yes" : "no"); +				vty_out(vty, +					"    Hello Option - Generation ID   : %s\n", +					option_generation_id ? "yes" : "no"); +				vty_out(vty, +					"    Hello Option - Holdtime        : %s\n", +					option_holdtime ? "yes" : "no"); +				vty_out(vty, +					"    Hello Option - LAN Prune Delay : %s\n", +					option_lan_prune_delay ? "yes" : "no"); +				vty_out(vty, +					"    Hello Option - T-bit           : %s\n", +					option_t_bit ? "yes" : "no"); +				pim_bfd_show_info(vty, neigh->bfd_info, +						  json_ifp, uj, 0); +				vty_out(vty, "\n"); +			} +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} else { +		{ +			if (!found_neighbor) +				vty_out(vty, +					"%% No such interface or neighbor\n"); +		} +	} +} + +static void pim_show_state(struct vty *vty, const char *src_or_group, +			   const char *group, u_char uj) +{ +	struct channel_oil *c_oil; +	struct listnode *node; +	json_object *json = NULL; +	json_object *json_group = NULL; +	json_object *json_ifp_in = NULL; +	json_object *json_ifp_out = NULL; +	json_object *json_source = NULL; +	time_t now; +	int first_oif; +	now = pim_time_monotonic_sec(); + +	if (uj) { +		json = json_object_new_object(); +	} else { +		vty_out(vty, +			"Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); +		vty_out(vty, +			"\nInstalled Source           Group            IIF      OIL\n"); +	} + +	for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { +		char grp_str[INET_ADDRSTRLEN]; +		char src_str[INET_ADDRSTRLEN]; +		char in_ifname[INTERFACE_NAMSIZ + 1]; +		char out_ifname[INTERFACE_NAMSIZ + 1]; +		int oif_vif_index; +		struct interface *ifp_in; +		first_oif = 1; + +		pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, +			       sizeof(grp_str)); +		pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, +			       sizeof(src_str)); +		ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + +		if (ifp_in) +			strcpy(in_ifname, ifp_in->name); +		else +			strcpy(in_ifname, "<iif?>"); + +		if (src_or_group) { +			if (strcmp(src_or_group, src_str) +			    && strcmp(src_or_group, grp_str)) +				continue; + +			if (group && strcmp(group, grp_str)) +				continue; +		} + +		if (uj) { + +			/* Find the group, create it if it doesn't exist */ +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			/* Find the source nested under the group, create it if +			 * it doesn't exist */ +			json_object_object_get_ex(json_group, src_str, +						  &json_source); + +			if (!json_source) { +				json_source = json_object_new_object(); +				json_object_object_add(json_group, src_str, +						       json_source); +			} + +			/* Find the inbound interface nested under the source, +			 * create it if it doesn't exist */ +			json_object_object_get_ex(json_source, in_ifname, +						  &json_ifp_in); + +			if (!json_ifp_in) { +				json_ifp_in = json_object_new_object(); +				json_object_object_add(json_source, in_ifname, +						       json_ifp_in); +				json_object_int_add(json_source, "Installed", +						    c_oil->installed); +				json_object_int_add(json_source, "RefCount", +						    c_oil->oil_ref_count); +				json_object_int_add(json_source, "OilListSize", +						    c_oil->oil_size); +				json_object_int_add( +					json_source, "OilRescan", +					c_oil->oil_inherited_rescan); +				json_object_int_add(json_source, "LastUsed", +						    c_oil->cc.lastused); +				json_object_int_add(json_source, "PacketCount", +						    c_oil->cc.pktcnt); +				json_object_int_add(json_source, "ByteCount", +						    c_oil->cc.bytecnt); +				json_object_int_add(json_source, +						    "WrongInterface", +						    c_oil->cc.wrong_if); +			} +		} else { +			vty_out(vty, "%-9d %-15s  %-15s  %-7s  ", +				c_oil->installed, src_str, grp_str, +				ifp_in->name); +		} + +		for (oif_vif_index = 0; oif_vif_index < MAXVIFS; +		     ++oif_vif_index) { +			struct interface *ifp_out; +			char oif_uptime[10]; +			int ttl; + +			ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; +			if (ttl < 1) +				continue; + +			ifp_out = pim_if_find_by_vif_index(oif_vif_index); +			pim_time_uptime( +				oif_uptime, sizeof(oif_uptime), +				now - c_oil->oif_creation[oif_vif_index]); + +			if (ifp_out) +				strcpy(out_ifname, ifp_out->name); +			else +				strcpy(out_ifname, "<oif?>"); + +			if (uj) { +				json_ifp_out = json_object_new_object(); +				json_object_string_add(json_ifp_out, "source", +						       src_str); +				json_object_string_add(json_ifp_out, "group", +						       grp_str); +				json_object_string_add(json_ifp_out, +						       "inboundInterface", +						       in_ifname); +				json_object_string_add(json_ifp_out, +						       "outboundInterface", +						       out_ifname); +				json_object_int_add(json_ifp_out, "installed", +						    c_oil->installed); + +				json_object_object_add(json_ifp_in, out_ifname, +						       json_ifp_out); +			} else { +				if (first_oif) { +					first_oif = 0; +					vty_out(vty, "%s(%c%c%c%c)", out_ifname, +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_IGMP) +							? 'I' +							: ' ', +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_PIM) +							? 'J' +							: ' ', +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_SOURCE) +							? 'S' +							: ' ', +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_STAR) +							? '*' +							: ' '); +				} else +					vty_out(vty, ", %s(%c%c%c%c)", +						out_ifname, +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_IGMP) +							? 'I' +							: ' ', +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_PIM) +							? 'J' +							: ' ', +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_SOURCE) +							? 'S' +							: ' ', +						(c_oil->oif_flags[oif_vif_index] +						 & PIM_OIF_FLAG_PROTO_STAR) +							? '*' +							: ' '); +			} +		} + +		if (!uj) +			vty_out(vty, "\n"); +	} + + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} else { +		vty_out(vty, "\n"); +	}  }  static void pim_show_neighbors(struct vty *vty, u_char uj)  { -  struct listnode *node; -  struct listnode *neighnode; -  struct interface *ifp; -  struct pim_interface *pim_ifp; -  struct pim_neighbor *neigh; -  time_t now; -  char uptime[10]; -  char expire[10]; -  char neigh_src_str[INET_ADDRSTRLEN]; -  json_object *json = NULL; -  json_object *json_ifp_rows = NULL; -  json_object *json_row = NULL; - -  now = pim_time_monotonic_sec(); - -  if (uj) { -    json = json_object_new_object(); -  } else { -    vty_out (vty, "Interface         Neighbor    Uptime  Holdtime  DR Pri\n"); -  } - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    pim_ifp = ifp->info; - -    if (!pim_ifp) -      continue; - -    if (pim_ifp->pim_sock_fd < 0) -      continue; - -    if (uj) -      json_ifp_rows = json_object_new_object(); - -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { -      pim_inet4_dump("<src?>", neigh->source_addr, -		     neigh_src_str, sizeof(neigh_src_str)); -      pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); -      pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - -      if (uj) { -        json_row = json_object_new_object(); -        json_object_string_add(json_row, "interface", ifp->name); -        json_object_string_add(json_row, "neighbor", neigh_src_str); -        json_object_string_add(json_row, "upTime", uptime); -        json_object_string_add(json_row, "holdTime", expire); -        json_object_int_add(json_row, "holdTimeMax", neigh->holdtime); -        json_object_int_add(json_row, "drPriority", neigh->dr_priority); -        json_object_object_add(json_ifp_rows, neigh_src_str, json_row); - -      } else { -        vty_out (vty, "%-9s  %15s  %8s  %8s  %6d\n", -                ifp->name, -                neigh_src_str, -                uptime, -                expire, -                neigh->dr_priority); -      } -    } - -    if (uj) { -      json_object_object_add(json, ifp->name, json_ifp_rows); -      json_ifp_rows = NULL; -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	struct listnode *node; +	struct listnode *neighnode; +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	struct pim_neighbor *neigh; +	time_t now; +	char uptime[10]; +	char expire[10]; +	char neigh_src_str[INET_ADDRSTRLEN]; +	json_object *json = NULL; +	json_object *json_ifp_rows = NULL; +	json_object *json_row = NULL; + +	now = pim_time_monotonic_sec(); + +	if (uj) { +		json = json_object_new_object(); +	} else { +		vty_out(vty, +			"Interface         Neighbor    Uptime  Holdtime  DR Pri\n"); +	} + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		if (pim_ifp->pim_sock_fd < 0) +			continue; + +		if (uj) +			json_ifp_rows = json_object_new_object(); + +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, +					  neigh)) { +			pim_inet4_dump("<src?>", neigh->source_addr, +				       neigh_src_str, sizeof(neigh_src_str)); +			pim_time_uptime(uptime, sizeof(uptime), +					now - neigh->creation); +			pim_time_timer_to_hhmmss(expire, sizeof(expire), +						 neigh->t_expire_timer); + +			if (uj) { +				json_row = json_object_new_object(); +				json_object_string_add(json_row, "interface", +						       ifp->name); +				json_object_string_add(json_row, "neighbor", +						       neigh_src_str); +				json_object_string_add(json_row, "upTime", +						       uptime); +				json_object_string_add(json_row, "holdTime", +						       expire); +				json_object_int_add(json_row, "holdTimeMax", +						    neigh->holdtime); +				json_object_int_add(json_row, "drPriority", +						    neigh->dr_priority); +				json_object_object_add(json_ifp_rows, +						       neigh_src_str, json_row); + +			} else { +				vty_out(vty, "%-9s  %15s  %8s  %8s  %6d\n", +					ifp->name, neigh_src_str, uptime, +					expire, neigh->dr_priority); +			} +		} + +		if (uj) { +			json_object_object_add(json, ifp->name, json_ifp_rows); +			json_ifp_rows = NULL; +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  static void pim_show_neighbors_secondary(struct vty *vty)  { -  struct listnode  *node; -  struct interface *ifp; +	struct listnode *node; +	struct interface *ifp; -  vty_out (vty, -            "Interface Address         Neighbor        Secondary      \n"); +	vty_out(vty, +		"Interface Address         Neighbor        Secondary      \n"); -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    struct pim_interface *pim_ifp; -    struct in_addr ifaddr; -    struct listnode *neighnode; -    struct pim_neighbor *neigh; +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		struct pim_interface *pim_ifp; +		struct in_addr ifaddr; +		struct listnode *neighnode; +		struct pim_neighbor *neigh; -    pim_ifp = ifp->info; -     -    if (!pim_ifp) -      continue; +		pim_ifp = ifp->info; -    if (pim_ifp->pim_sock_fd < 0) -      continue; +		if (!pim_ifp) +			continue; -    ifaddr = pim_ifp->primary_address; +		if (pim_ifp->pim_sock_fd < 0) +			continue; -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { -      char neigh_src_str[INET_ADDRSTRLEN]; -      struct listnode *prefix_node; -      struct prefix *p; +		ifaddr = pim_ifp->primary_address; -      if (!neigh->prefix_list) -	continue; +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, +					  neigh)) { +			char neigh_src_str[INET_ADDRSTRLEN]; +			struct listnode *prefix_node; +			struct prefix *p; -      pim_inet4_dump("<src?>", neigh->source_addr, -		     neigh_src_str, sizeof(neigh_src_str)); +			if (!neigh->prefix_list) +				continue; -      for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) { -	char neigh_sec_str[PREFIX2STR_BUFFER]; +			pim_inet4_dump("<src?>", neigh->source_addr, +				       neigh_src_str, sizeof(neigh_src_str)); -	prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str)); +			for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, +						  prefix_node, p)) { +				char neigh_sec_str[PREFIX2STR_BUFFER]; -	vty_out (vty, "%-9s %-15s %-15s %-15s\n", -		ifp->name, -		inet_ntoa(ifaddr), -		neigh_src_str, -		neigh_sec_str); -      } -    } -  } +				prefix2str(p, neigh_sec_str, +					   sizeof(neigh_sec_str)); + +				vty_out(vty, "%-9s %-15s %-15s %-15s\n", +					ifp->name, inet_ntoa(ifaddr), +					neigh_src_str, neigh_sec_str); +			} +		} +	}  } -static void -json_object_pim_upstream_add (json_object *json, struct pim_upstream *up) +static void json_object_pim_upstream_add(json_object *json, +					 struct pim_upstream *up)  { -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) -    json_object_boolean_true_add(json, "drJoinDesired"); - -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) -    json_object_boolean_true_add(json, "drJoinDesiredUpdated"); +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) +		json_object_boolean_true_add(json, "drJoinDesired"); -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) -    json_object_boolean_true_add(json, "firstHopRouter"); +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) +		json_object_boolean_true_add(json, "drJoinDesiredUpdated"); -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) -    json_object_boolean_true_add(json, "sourceIgmp"); +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) +		json_object_boolean_true_add(json, "firstHopRouter"); -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) -    json_object_boolean_true_add(json, "sourcePim"); +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) +		json_object_boolean_true_add(json, "sourceIgmp"); -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) -    json_object_boolean_true_add(json, "sourceStream"); +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) +		json_object_boolean_true_add(json, "sourcePim"); -  /* XXX: need to print ths flag in the plain text display as well */ -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) -    json_object_boolean_true_add(json, "sourceMsdp"); -} +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) +		json_object_boolean_true_add(json, "sourceStream"); -static const char * -pim_upstream_state2brief_str (enum pim_upstream_state join_state, char *state_str) -{ -  switch (join_state) -    { -    case PIM_UPSTREAM_NOTJOINED: -      strcpy (state_str, "NotJ"); -      break; -    case PIM_UPSTREAM_JOINED: -      strcpy (state_str, "J"); -      break; -    default: -      strcpy (state_str, "Unk"); -    } -  return state_str; +	/* XXX: need to print ths flag in the plain text display as well */ +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) +		json_object_boolean_true_add(json, "sourceMsdp");  }  static const char * -pim_reg_state2brief_str (enum pim_reg_state reg_state, char *state_str) -{ -  switch (reg_state) -    { -    case PIM_REG_NOINFO: -      strcpy (state_str, "RegNI"); -      break; -    case PIM_REG_JOIN: -      strcpy (state_str, "RegJ"); -      break; -    case PIM_REG_JOIN_PENDING: -    case PIM_REG_PRUNE: -      strcpy (state_str, "RegP"); -      break; -    default: -      strcpy (state_str, "Unk"); -    } -  return state_str; +pim_upstream_state2brief_str(enum pim_upstream_state join_state, +			     char *state_str) +{ +	switch (join_state) { +	case PIM_UPSTREAM_NOTJOINED: +		strcpy(state_str, "NotJ"); +		break; +	case PIM_UPSTREAM_JOINED: +		strcpy(state_str, "J"); +		break; +	default: +		strcpy(state_str, "Unk"); +	} +	return state_str; +} + +static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, +					   char *state_str) +{ +	switch (reg_state) { +	case PIM_REG_NOINFO: +		strcpy(state_str, "RegNI"); +		break; +	case PIM_REG_JOIN: +		strcpy(state_str, "RegJ"); +		break; +	case PIM_REG_JOIN_PENDING: +	case PIM_REG_PRUNE: +		strcpy(state_str, "RegP"); +		break; +	default: +		strcpy(state_str, "Unk"); +	} +	return state_str;  }  static void pim_show_upstream(struct vty *vty, u_char uj)  { -  struct listnode     *upnode; -  struct pim_upstream *up; -  time_t               now; -  json_object *json = NULL; -  json_object *json_group = NULL; -  json_object *json_row = NULL; - -  now = pim_time_monotonic_sec(); - -  if (uj) -    json = json_object_new_object(); -  else -    vty_out (vty, -              "Iif       Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n"); - -  for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { -    char src_str[INET_ADDRSTRLEN]; -    char grp_str[INET_ADDRSTRLEN]; -    char uptime[10]; -    char join_timer[10]; -    char rs_timer[10]; -    char ka_timer[10]; -    char msdp_reg_timer[10]; -    char state_str[PIM_REG_STATE_STR_LEN]; - -    pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); -    pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); -    pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer); - -    /* -     * If we have a J/P timer for the neighbor display that -     */ -    if (!up->t_join_timer) -      { -        struct pim_neighbor *nbr; - -        nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, -                                 up->rpf.rpf_addr.u.prefix4); -        if (nbr) -          pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), nbr->jp_timer); -      } - -    pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); -    pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); -    pim_time_timer_to_hhmmss (msdp_reg_timer, sizeof (msdp_reg_timer), up->t_msdp_reg_timer); - -    pim_upstream_state2brief_str (up->join_state, state_str); -    if (up->reg_state != PIM_REG_NOINFO) { -      char tmp_str[PIM_REG_STATE_STR_LEN]; - -      sprintf (state_str + strlen (state_str), ",%s", -               pim_reg_state2brief_str (up->reg_state, tmp_str)); -    } - -    if (uj) { -      json_object_object_get_ex(json, grp_str, &json_group); - -      if (!json_group) { -        json_group = json_object_new_object(); -        json_object_object_add(json, grp_str, json_group); -      } - -      json_row = json_object_new_object(); -      json_object_pim_upstream_add(json_row, up); -      json_object_string_add(json_row, "inboundInterface", up->rpf.source_nexthop.interface->name); -      json_object_string_add(json_row, "source", src_str); -      json_object_string_add(json_row, "group", grp_str); -      json_object_string_add(json_row, "state", state_str); -      json_object_string_add(json_row, "joinState", pim_upstream_state2str (up->join_state)); -      json_object_string_add(json_row, "regState", pim_reg_state2str (up->reg_state, state_str)); -      json_object_string_add(json_row, "upTime", uptime); -      json_object_string_add(json_row, "joinTimer", join_timer); -      json_object_string_add(json_row, "resetTimer", rs_timer); -      json_object_string_add(json_row, "keepaliveTimer", ka_timer); -      json_object_string_add(json_row, "msdpRegTimer", msdp_reg_timer); -      json_object_int_add(json_row, "refCount", up->ref_count); -      json_object_int_add(json_row, "sptBit", up->sptbit); -      json_object_object_add(json_group, src_str, json_row); -    } else { -      vty_out (vty, "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", -              up->rpf.source_nexthop.interface->name, -              src_str, -              grp_str, -              state_str, -              uptime, -              join_timer, -              rs_timer, -              ka_timer, -              up->ref_count); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	struct listnode *upnode; +	struct pim_upstream *up; +	time_t now; +	json_object *json = NULL; +	json_object *json_group = NULL; +	json_object *json_row = NULL; + +	now = pim_time_monotonic_sec(); + +	if (uj) +		json = json_object_new_object(); +	else +		vty_out(vty, +			"Iif       Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n"); + +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { +		char src_str[INET_ADDRSTRLEN]; +		char grp_str[INET_ADDRSTRLEN]; +		char uptime[10]; +		char join_timer[10]; +		char rs_timer[10]; +		char ka_timer[10]; +		char msdp_reg_timer[10]; +		char state_str[PIM_REG_STATE_STR_LEN]; + +		pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); +		pim_time_uptime(uptime, sizeof(uptime), +				now - up->state_transition); +		pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), +					 up->t_join_timer); + +		/* +		 * If we have a J/P timer for the neighbor display that +		 */ +		if (!up->t_join_timer) { +			struct pim_neighbor *nbr; + +			nbr = pim_neighbor_find( +				up->rpf.source_nexthop.interface, +				up->rpf.rpf_addr.u.prefix4); +			if (nbr) +				pim_time_timer_to_hhmmss(join_timer, +							 sizeof(join_timer), +							 nbr->jp_timer); +		} + +		pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer), +					 up->t_rs_timer); +		pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer), +					 up->t_ka_timer); +		pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer), +					 up->t_msdp_reg_timer); + +		pim_upstream_state2brief_str(up->join_state, state_str); +		if (up->reg_state != PIM_REG_NOINFO) { +			char tmp_str[PIM_REG_STATE_STR_LEN]; + +			sprintf(state_str + strlen(state_str), ",%s", +				pim_reg_state2brief_str(up->reg_state, +							tmp_str)); +		} + +		if (uj) { +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			json_row = json_object_new_object(); +			json_object_pim_upstream_add(json_row, up); +			json_object_string_add( +				json_row, "inboundInterface", +				up->rpf.source_nexthop.interface->name); +			json_object_string_add(json_row, "source", src_str); +			json_object_string_add(json_row, "group", grp_str); +			json_object_string_add(json_row, "state", state_str); +			json_object_string_add( +				json_row, "joinState", +				pim_upstream_state2str(up->join_state)); +			json_object_string_add( +				json_row, "regState", +				pim_reg_state2str(up->reg_state, state_str)); +			json_object_string_add(json_row, "upTime", uptime); +			json_object_string_add(json_row, "joinTimer", +					       join_timer); +			json_object_string_add(json_row, "resetTimer", +					       rs_timer); +			json_object_string_add(json_row, "keepaliveTimer", +					       ka_timer); +			json_object_string_add(json_row, "msdpRegTimer", +					       msdp_reg_timer); +			json_object_int_add(json_row, "refCount", +					    up->ref_count); +			json_object_int_add(json_row, "sptBit", up->sptbit); +			json_object_object_add(json_group, src_str, json_row); +		} else { +			vty_out(vty, +				"%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", +				up->rpf.source_nexthop.interface->name, src_str, +				grp_str, state_str, uptime, join_timer, +				rs_timer, ka_timer, up->ref_count); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  static void pim_show_join_desired(struct vty *vty, u_char uj)  { -  struct listnode      *chnode; -  struct pim_interface *pim_ifp; -  struct pim_ifchannel *ch; -  char src_str[INET_ADDRSTRLEN]; -  char grp_str[INET_ADDRSTRLEN]; -  json_object *json = NULL; -  json_object *json_group = NULL; -  json_object *json_row = NULL; - -  if (uj) -    json = json_object_new_object(); -  else -    vty_out (vty, -            "Interface Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n"); - -  /* scan per-interface (S,G) state */ -  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) { -    /* scan all interfaces */ -    pim_ifp = ch->interface->info; -    if (!pim_ifp) -      continue; - -    struct pim_upstream *up = ch->upstream; - -    pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - -    if (uj) { -      json_object_object_get_ex(json, grp_str, &json_group); - -      if (!json_group) { -	json_group = json_object_new_object(); -	json_object_object_add(json, grp_str, json_group); -      } - -      json_row = json_object_new_object(); -      json_object_pim_upstream_add(json_row, up); -      json_object_string_add(json_row, "interface", ch->interface->name); -      json_object_string_add(json_row, "source", src_str); -      json_object_string_add(json_row, "group", grp_str); - -      if (pim_macro_ch_lost_assert(ch)) -	json_object_boolean_true_add(json_row, "lostAssert"); - -      if (pim_macro_chisin_joins(ch)) -	json_object_boolean_true_add(json_row, "joins"); - -      if (pim_macro_chisin_pim_include(ch)) -	json_object_boolean_true_add(json_row, "pimInclude"); - -      if (pim_upstream_evaluate_join_desired(up)) -	json_object_boolean_true_add(json_row, "evaluateJoinDesired"); - -      json_object_object_add(json_group, src_str, json_row); - -    } else { -      vty_out (vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", -	      ch->interface->name, -	      src_str, -	      grp_str, -	      pim_macro_ch_lost_assert(ch) ? "yes" : "no", -	      pim_macro_chisin_joins(ch) ? "yes" : "no", -	      pim_macro_chisin_pim_include(ch) ? "yes" : "no", -	      PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no", -	      pim_upstream_evaluate_join_desired(up) ? "yes" : "no"); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	struct listnode *chnode; +	struct pim_interface *pim_ifp; +	struct pim_ifchannel *ch; +	char src_str[INET_ADDRSTRLEN]; +	char grp_str[INET_ADDRSTRLEN]; +	json_object *json = NULL; +	json_object *json_group = NULL; +	json_object *json_row = NULL; + +	if (uj) +		json = json_object_new_object(); +	else +		vty_out(vty, +			"Interface Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n"); + +	/* scan per-interface (S,G) state */ +	for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) { +		/* scan all interfaces */ +		pim_ifp = ch->interface->info; +		if (!pim_ifp) +			continue; + +		struct pim_upstream *up = ch->upstream; + +		pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); + +		if (uj) { +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			json_row = json_object_new_object(); +			json_object_pim_upstream_add(json_row, up); +			json_object_string_add(json_row, "interface", +					       ch->interface->name); +			json_object_string_add(json_row, "source", src_str); +			json_object_string_add(json_row, "group", grp_str); + +			if (pim_macro_ch_lost_assert(ch)) +				json_object_boolean_true_add(json_row, +							     "lostAssert"); + +			if (pim_macro_chisin_joins(ch)) +				json_object_boolean_true_add(json_row, "joins"); + +			if (pim_macro_chisin_pim_include(ch)) +				json_object_boolean_true_add(json_row, +							     "pimInclude"); + +			if (pim_upstream_evaluate_join_desired(up)) +				json_object_boolean_true_add( +					json_row, "evaluateJoinDesired"); + +			json_object_object_add(json_group, src_str, json_row); + +		} else { +			vty_out(vty, +				"%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", +				ch->interface->name, src_str, grp_str, +				pim_macro_ch_lost_assert(ch) ? "yes" : "no", +				pim_macro_chisin_joins(ch) ? "yes" : "no", +				pim_macro_chisin_pim_include(ch) ? "yes" : "no", +				PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED( +					up->flags) +					? "yes" +					: "no", +				pim_upstream_evaluate_join_desired(up) ? "yes" +								       : "no"); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  static void pim_show_upstream_rpf(struct vty *vty, u_char uj)  { -  struct listnode     *upnode; -  struct pim_upstream *up; -  json_object *json = NULL; -  json_object *json_group = NULL; -  json_object *json_row = NULL; - -  if (uj) -    json = json_object_new_object(); -  else -    vty_out (vty, -            "Source          Group           RpfIface RibNextHop      RpfAddress     \n"); - -  for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { -    char src_str[INET_ADDRSTRLEN]; -    char grp_str[INET_ADDRSTRLEN]; -    char rpf_nexthop_str[PREFIX_STRLEN]; -    char rpf_addr_str[PREFIX_STRLEN]; -    struct pim_rpf *rpf; -    const char *rpf_ifname; - -    rpf = &up->rpf; - -    pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); -    pim_addr_dump("<nexthop?>", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); -    pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - -    rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; - -    if (uj) { -        json_object_object_get_ex(json, grp_str, &json_group); - -        if (!json_group) { -          json_group = json_object_new_object(); -          json_object_object_add(json, grp_str, json_group); -        } - -        json_row = json_object_new_object(); -        json_object_pim_upstream_add(json_row, up); -        json_object_string_add(json_row, "source", src_str); -        json_object_string_add(json_row, "group", grp_str); -        json_object_string_add(json_row, "rpfInterface", rpf_ifname); -        json_object_string_add(json_row, "ribNexthop", rpf_nexthop_str); -        json_object_string_add(json_row, "rpfAddress", rpf_addr_str); -        json_object_object_add(json_group, src_str, json_row); -    } else { -        vty_out (vty, "%-15s %-15s %-8s %-15s %-15s\n", -                src_str, -                grp_str, -                rpf_ifname, -                rpf_nexthop_str, -                rpf_addr_str); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } -} - -static void show_rpf_refresh_stats(struct vty *vty, time_t now, json_object *json) -{ -  char refresh_uptime[10]; - -  pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, qpim_rpf_cache_refresh_last); - -  if (json) { -    json_object_int_add(json, "rpfCacheRefreshDelayMsecs", qpim_rpf_cache_refresh_delay_msec); -    json_object_int_add(json, "rpfCacheRefreshTimer", pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); -    json_object_int_add(json, "rpfCacheRefreshRequests", qpim_rpf_cache_refresh_requests); -    json_object_int_add(json, "rpfCacheRefreshEvents", qpim_rpf_cache_refresh_events); -    json_object_string_add(json, "rpfCacheRefreshLast", refresh_uptime); -    json_object_int_add(json, "nexthopLookups", qpim_nexthop_lookups); -    json_object_int_add(json, "nexthopLookupsAvoided", nexthop_lookups_avoided); -  } else { -    vty_out (vty, -            "RPF Cache Refresh Delay:    %ld msecs\n" -            "RPF Cache Refresh Timer:    %ld msecs\n" -            "RPF Cache Refresh Requests: %lld\n" -            "RPF Cache Refresh Events:   %lld\n" -            "RPF Cache Refresh Last:     %s\n" -            "Nexthop Lookups:            %lld\n" -	    "Nexthop Lookups Avoided:    %lld\n", -            qpim_rpf_cache_refresh_delay_msec, -            pim_time_timer_remain_msec(qpim_rpf_cache_refresher), -            (long long)qpim_rpf_cache_refresh_requests, -            (long long)qpim_rpf_cache_refresh_events, -            refresh_uptime, -            (long long) qpim_nexthop_lookups, -	    (long long)nexthop_lookups_avoided); -  } +	struct listnode *upnode; +	struct pim_upstream *up; +	json_object *json = NULL; +	json_object *json_group = NULL; +	json_object *json_row = NULL; + +	if (uj) +		json = json_object_new_object(); +	else +		vty_out(vty, +			"Source          Group           RpfIface RibNextHop      RpfAddress     \n"); + +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { +		char src_str[INET_ADDRSTRLEN]; +		char grp_str[INET_ADDRSTRLEN]; +		char rpf_nexthop_str[PREFIX_STRLEN]; +		char rpf_addr_str[PREFIX_STRLEN]; +		struct pim_rpf *rpf; +		const char *rpf_ifname; + +		rpf = &up->rpf; + +		pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); +		pim_addr_dump("<nexthop?>", +			      &rpf->source_nexthop.mrib_nexthop_addr, +			      rpf_nexthop_str, sizeof(rpf_nexthop_str)); +		pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, +			      sizeof(rpf_addr_str)); + +		rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; + +		if (uj) { +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			json_row = json_object_new_object(); +			json_object_pim_upstream_add(json_row, up); +			json_object_string_add(json_row, "source", src_str); +			json_object_string_add(json_row, "group", grp_str); +			json_object_string_add(json_row, "rpfInterface", +					       rpf_ifname); +			json_object_string_add(json_row, "ribNexthop", +					       rpf_nexthop_str); +			json_object_string_add(json_row, "rpfAddress", +					       rpf_addr_str); +			json_object_object_add(json_group, src_str, json_row); +		} else { +			vty_out(vty, "%-15s %-15s %-8s %-15s %-15s\n", src_str, +				grp_str, rpf_ifname, rpf_nexthop_str, +				rpf_addr_str); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} +} + +static void show_rpf_refresh_stats(struct vty *vty, time_t now, +				   json_object *json) +{ +	char refresh_uptime[10]; + +	pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, +			      qpim_rpf_cache_refresh_last); + +	if (json) { +		json_object_int_add(json, "rpfCacheRefreshDelayMsecs", +				    qpim_rpf_cache_refresh_delay_msec); +		json_object_int_add( +			json, "rpfCacheRefreshTimer", +			pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); +		json_object_int_add(json, "rpfCacheRefreshRequests", +				    qpim_rpf_cache_refresh_requests); +		json_object_int_add(json, "rpfCacheRefreshEvents", +				    qpim_rpf_cache_refresh_events); +		json_object_string_add(json, "rpfCacheRefreshLast", +				       refresh_uptime); +		json_object_int_add(json, "nexthopLookups", +				    qpim_nexthop_lookups); +		json_object_int_add(json, "nexthopLookupsAvoided", +				    nexthop_lookups_avoided); +	} else { +		vty_out(vty, +			"RPF Cache Refresh Delay:    %ld msecs\n" +			"RPF Cache Refresh Timer:    %ld msecs\n" +			"RPF Cache Refresh Requests: %lld\n" +			"RPF Cache Refresh Events:   %lld\n" +			"RPF Cache Refresh Last:     %s\n" +			"Nexthop Lookups:            %lld\n" +			"Nexthop Lookups Avoided:    %lld\n", +			qpim_rpf_cache_refresh_delay_msec, +			pim_time_timer_remain_msec(qpim_rpf_cache_refresher), +			(long long)qpim_rpf_cache_refresh_requests, +			(long long)qpim_rpf_cache_refresh_events, +			refresh_uptime, (long long)qpim_nexthop_lookups, +			(long long)nexthop_lookups_avoided); +	}  }  static void show_scan_oil_stats(struct vty *vty, time_t now)  { -  char uptime_scan_oil[10]; -  char uptime_mroute_add[10]; -  char uptime_mroute_del[10]; +	char uptime_scan_oil[10]; +	char uptime_mroute_add[10]; +	char uptime_mroute_del[10]; -  pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, qpim_scan_oil_last); -  pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, qpim_mroute_add_last); -  pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, qpim_mroute_del_last); +	pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, +			      qpim_scan_oil_last); +	pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, +			      qpim_mroute_add_last); +	pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, +			      qpim_mroute_del_last); -  vty_out (vty, -          "Scan OIL - Last: %s  Events: %lld\n" -          "MFC Add  - Last: %s  Events: %lld\n" -          "MFC Del  - Last: %s  Events: %lld\n", -          uptime_scan_oil,   (long long) qpim_scan_oil_events, -          uptime_mroute_add, (long long) qpim_mroute_add_events, -          uptime_mroute_del, (long long)qpim_mroute_del_events); +	vty_out(vty, +		"Scan OIL - Last: %s  Events: %lld\n" +		"MFC Add  - Last: %s  Events: %lld\n" +		"MFC Del  - Last: %s  Events: %lld\n", +		uptime_scan_oil, (long long)qpim_scan_oil_events, +		uptime_mroute_add, (long long)qpim_mroute_add_events, +		uptime_mroute_del, (long long)qpim_mroute_del_events);  }  static void pim_show_rpf(struct vty *vty, u_char uj)  { -  struct listnode     *up_node; -  struct pim_upstream *up; -  time_t               now = pim_time_monotonic_sec(); -  json_object *json = NULL; -  json_object *json_group = NULL; -  json_object *json_row = NULL; - -  if (uj) { -    json = json_object_new_object(); -    show_rpf_refresh_stats(vty, now, json); -  } else { -    show_rpf_refresh_stats(vty, now, json); -    vty_out (vty, "\n"); -    vty_out (vty, -            "Source          Group           RpfIface RpfAddress      RibNextHop      Metric Pref\n"); -  } - -  for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { -    char src_str[INET_ADDRSTRLEN]; -    char grp_str[INET_ADDRSTRLEN]; -    char rpf_addr_str[PREFIX_STRLEN]; -    char rib_nexthop_str[PREFIX_STRLEN]; -    const char *rpf_ifname; -    struct pim_rpf  *rpf = &up->rpf; -     -    pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); -    pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); -    pim_addr_dump("<nexthop?>", &rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); -     -    rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; -     -    if (uj) { -      json_object_object_get_ex(json, grp_str, &json_group); - -      if (!json_group) { -        json_group = json_object_new_object(); -        json_object_object_add(json, grp_str, json_group); -      } - -      json_row = json_object_new_object(); -      json_object_string_add(json_row, "source", src_str); -      json_object_string_add(json_row, "group", grp_str); -      json_object_string_add(json_row, "rpfInterface", rpf_ifname); -      json_object_string_add(json_row, "rpfAddress", rpf_addr_str); -      json_object_string_add(json_row, "ribNexthop", rib_nexthop_str); -      json_object_int_add(json_row, "routeMetric", rpf->source_nexthop.mrib_route_metric); -      json_object_int_add(json_row, "routePreference", rpf->source_nexthop.mrib_metric_preference); -      json_object_object_add(json_group, src_str, json_row); - -    } else { -      vty_out (vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n", -              src_str, -              grp_str, -              rpf_ifname, -              rpf_addr_str, -              rib_nexthop_str, -              rpf->source_nexthop.mrib_route_metric, -              rpf->source_nexthop.mrib_metric_preference); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } -} - -static int -pim_print_pnc_cache_walkcb (struct hash_backet *backet, void *arg) -{ -  struct pim_nexthop_cache *pnc = backet->data; -  struct vty *vty = arg; -  struct nexthop *nh_node = NULL; -  ifindex_t first_ifindex; -  struct interface *ifp = NULL; - -  if (!pnc) -    return CMD_SUCCESS; - -  for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) -    { -      first_ifindex = nh_node->ifindex; -      ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); - -      vty_out (vty, "%-15s ", inet_ntoa (pnc->rpf.rpf_addr.u.prefix4)); -      vty_out (vty, "%-14s ", ifp ? ifp->name : "NULL"); -      vty_out (vty, "%s ", inet_ntoa (nh_node->gate.ipv4)); -      vty_out (vty, "\n"); -    } -  return CMD_SUCCESS; -} - -static void -pim_show_nexthop (struct vty *vty) -{ - -  if (pimg && !pimg->rpf_hash) -    { -      vty_out (vty, "no nexthop cache \n"); -      return; -    } - -  vty_out (vty, "Number of registered addresses: %lu \n", -           pimg->rpf_hash->count); -  vty_out (vty, "Address         Interface      Nexthop\n"); -  vty_out (vty, "-------------------------------------------\n"); - -  hash_walk (pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty); +	struct listnode *up_node; +	struct pim_upstream *up; +	time_t now = pim_time_monotonic_sec(); +	json_object *json = NULL; +	json_object *json_group = NULL; +	json_object *json_row = NULL; + +	if (uj) { +		json = json_object_new_object(); +		show_rpf_refresh_stats(vty, now, json); +	} else { +		show_rpf_refresh_stats(vty, now, json); +		vty_out(vty, "\n"); +		vty_out(vty, +			"Source          Group           RpfIface RpfAddress      RibNextHop      Metric Pref\n"); +	} +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { +		char src_str[INET_ADDRSTRLEN]; +		char grp_str[INET_ADDRSTRLEN]; +		char rpf_addr_str[PREFIX_STRLEN]; +		char rib_nexthop_str[PREFIX_STRLEN]; +		const char *rpf_ifname; +		struct pim_rpf *rpf = &up->rpf; + +		pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); +		pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, +			      sizeof(rpf_addr_str)); +		pim_addr_dump("<nexthop?>", +			      &rpf->source_nexthop.mrib_nexthop_addr, +			      rib_nexthop_str, sizeof(rib_nexthop_str)); + +		rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; + +		if (uj) { +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			json_row = json_object_new_object(); +			json_object_string_add(json_row, "source", src_str); +			json_object_string_add(json_row, "group", grp_str); +			json_object_string_add(json_row, "rpfInterface", +					       rpf_ifname); +			json_object_string_add(json_row, "rpfAddress", +					       rpf_addr_str); +			json_object_string_add(json_row, "ribNexthop", +					       rib_nexthop_str); +			json_object_int_add( +				json_row, "routeMetric", +				rpf->source_nexthop.mrib_route_metric); +			json_object_int_add( +				json_row, "routePreference", +				rpf->source_nexthop.mrib_metric_preference); +			json_object_object_add(json_group, src_str, json_row); + +		} else { +			vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n", +				src_str, grp_str, rpf_ifname, rpf_addr_str, +				rib_nexthop_str, +				rpf->source_nexthop.mrib_route_metric, +				rpf->source_nexthop.mrib_metric_preference); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  } -static void igmp_show_groups(struct vty *vty, u_char uj) +static int pim_print_pnc_cache_walkcb(struct hash_backet *backet, void *arg)  { -  struct listnode  *ifnode; -  struct interface *ifp; -  time_t            now; -  json_object *json = NULL; -  json_object *json_iface = NULL; -  json_object *json_row = NULL; - -  now = pim_time_monotonic_sec(); - -  if (uj) -    json = json_object_new_object(); -  else -    vty_out (vty, -              "Interface Address         Group           Mode Timer    Srcs V Uptime  \n"); - -  /* scan interfaces */ -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { -    struct pim_interface *pim_ifp = ifp->info; -    struct listnode  *sock_node; -    struct igmp_sock *igmp; -     -    if (!pim_ifp) -      continue; -     -    /* scan igmp sockets */ -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      struct listnode *grpnode; -      struct igmp_group *grp; - -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - -      /* scan igmp groups */ -      for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { -	char group_str[INET_ADDRSTRLEN]; -	char hhmmss[10]; -	char uptime[10]; +	struct pim_nexthop_cache *pnc = backet->data; +	struct vty *vty = arg; +	struct nexthop *nh_node = NULL; +	ifindex_t first_ifindex; +	struct interface *ifp = NULL; + +	if (!pnc) +		return CMD_SUCCESS; + +	for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) { +		first_ifindex = nh_node->ifindex; +		ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + +		vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4)); +		vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL"); +		vty_out(vty, "%s ", inet_ntoa(nh_node->gate.ipv4)); +		vty_out(vty, "\n"); +	} +	return CMD_SUCCESS; +} + +static void pim_show_nexthop(struct vty *vty) +{ + +	if (pimg && !pimg->rpf_hash) { +		vty_out(vty, "no nexthop cache \n"); +		return; +	} + +	vty_out(vty, "Number of registered addresses: %lu \n", +		pimg->rpf_hash->count); +	vty_out(vty, "Address         Interface      Nexthop\n"); +	vty_out(vty, "-------------------------------------------\n"); -	pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); -	pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer); -	pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation); - -        if (uj) { -            json_object_object_get_ex(json, ifp->name, &json_iface); - -            if (!json_iface) { -              json_iface = json_object_new_object(); -              json_object_pim_ifp_add(json_iface, ifp); -              json_object_object_add(json, ifp->name, json_iface); -            } - -            json_row = json_object_new_object(); -            json_object_string_add(json_row, "source", ifaddr_str); -            json_object_string_add(json_row, "group", group_str); - -            if (grp->igmp_version == 3) -              json_object_string_add(json_row, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE"); - -            json_object_string_add(json_row, "timer", hhmmss); -            json_object_int_add(json_row, "sourcesCount", grp->group_source_list ? listcount(grp->group_source_list) : 0); -            json_object_int_add(json_row, "version", grp->igmp_version); -            json_object_string_add(json_row, "uptime", uptime); -            json_object_object_add(json_iface, group_str, json_row); - -        } else { -          vty_out (vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s\n", -                  ifp->name, -                  ifaddr_str, -                  group_str, -                  grp->igmp_version == 3 ? (grp->group_filtermode_isexcl ? "EXCL" : "INCL") : "----", -                  hhmmss, -                  grp->group_source_list ? listcount(grp->group_source_list) : 0, -                  grp->igmp_version, -                  uptime); -        } -      } /* scan igmp groups */ -    } /* scan igmp sockets */ -  } /* scan interfaces */ - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	hash_walk(pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty); +} + +static void igmp_show_groups(struct vty *vty, u_char uj) +{ +	struct listnode *ifnode; +	struct interface *ifp; +	time_t now; +	json_object *json = NULL; +	json_object *json_iface = NULL; +	json_object *json_row = NULL; + +	now = pim_time_monotonic_sec(); + +	if (uj) +		json = json_object_new_object(); +	else +		vty_out(vty, +			"Interface Address         Group           Mode Timer    Srcs V Uptime  \n"); + +	/* scan interfaces */ +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { +		struct pim_interface *pim_ifp = ifp->info; +		struct listnode *sock_node; +		struct igmp_sock *igmp; + +		if (!pim_ifp) +			continue; + +		/* scan igmp sockets */ +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, +					  igmp)) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			struct listnode *grpnode; +			struct igmp_group *grp; + +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); + +			/* scan igmp groups */ +			for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, +						  grpnode, grp)) { +				char group_str[INET_ADDRSTRLEN]; +				char hhmmss[10]; +				char uptime[10]; + +				pim_inet4_dump("<group?>", grp->group_addr, +					       group_str, sizeof(group_str)); +				pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), +							 grp->t_group_timer); +				pim_time_uptime(uptime, sizeof(uptime), +						now - grp->group_creation); + +				if (uj) { +					json_object_object_get_ex( +						json, ifp->name, &json_iface); + +					if (!json_iface) { +						json_iface = +							json_object_new_object(); +						json_object_pim_ifp_add( +							json_iface, ifp); +						json_object_object_add( +							json, ifp->name, +							json_iface); +					} + +					json_row = json_object_new_object(); +					json_object_string_add( +						json_row, "source", ifaddr_str); +					json_object_string_add( +						json_row, "group", group_str); + +					if (grp->igmp_version == 3) +						json_object_string_add( +							json_row, "mode", +							grp->group_filtermode_isexcl +								? "EXCLUDE" +								: "INCLUDE"); + +					json_object_string_add(json_row, +							       "timer", hhmmss); +					json_object_int_add( +						json_row, "sourcesCount", +						grp->group_source_list +							? listcount( +								  grp->group_source_list) +							: 0); +					json_object_int_add(json_row, "version", +							    grp->igmp_version); +					json_object_string_add( +						json_row, "uptime", uptime); +					json_object_object_add(json_iface, +							       group_str, +							       json_row); + +				} else { +					vty_out(vty, +						"%-9s %-15s %-15s %4s %8s %4d %d %8s\n", +						ifp->name, ifaddr_str, +						group_str, +						grp->igmp_version == 3 +							? (grp->group_filtermode_isexcl +								   ? "EXCL" +								   : "INCL") +							: "----", +						hhmmss, +						grp->group_source_list +							? listcount( +								  grp->group_source_list) +							: 0, +						grp->igmp_version, uptime); +				} +			} /* scan igmp groups */ +		}	 /* scan igmp sockets */ +	}		  /* scan interfaces */ + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  static void igmp_show_group_retransmission(struct vty *vty)  { -  struct listnode  *ifnode; -  struct interface *ifp; - -  vty_out (vty, -            "Interface Address         Group           RetTimer Counter RetSrcs\n"); - -  /* scan interfaces */ -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { -    struct pim_interface *pim_ifp = ifp->info; -    struct listnode  *sock_node; -    struct igmp_sock *igmp; -     -    if (!pim_ifp) -      continue; -     -    /* scan igmp sockets */ -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      struct listnode *grpnode; -      struct igmp_group *grp; - -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - -      /* scan igmp groups */ -      for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { -	char group_str[INET_ADDRSTRLEN]; -	char grp_retr_mmss[10]; -	struct listnode    *src_node; -	struct igmp_source *src; -	int grp_retr_sources = 0; - -	pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); -	pim_time_timer_to_mmss(grp_retr_mmss, sizeof(grp_retr_mmss), grp->t_group_query_retransmit_timer); - - -	/* count group sources with retransmission state */ -	for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) { -	  if (src->source_query_retransmit_count > 0) { -	    ++grp_retr_sources; -	  } -	} - -	vty_out (vty, "%-9s %-15s %-15s %-8s %7d %7d\n", -		ifp->name, -		ifaddr_str, -		group_str, -		grp_retr_mmss, -		grp->group_specific_query_retransmit_count, -		grp_retr_sources); - -      } /* scan igmp groups */ -    } /* scan igmp sockets */ -  } /* scan interfaces */ +	struct listnode *ifnode; +	struct interface *ifp; + +	vty_out(vty, +		"Interface Address         Group           RetTimer Counter RetSrcs\n"); + +	/* scan interfaces */ +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { +		struct pim_interface *pim_ifp = ifp->info; +		struct listnode *sock_node; +		struct igmp_sock *igmp; + +		if (!pim_ifp) +			continue; + +		/* scan igmp sockets */ +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, +					  igmp)) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			struct listnode *grpnode; +			struct igmp_group *grp; + +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); + +			/* scan igmp groups */ +			for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, +						  grpnode, grp)) { +				char group_str[INET_ADDRSTRLEN]; +				char grp_retr_mmss[10]; +				struct listnode *src_node; +				struct igmp_source *src; +				int grp_retr_sources = 0; + +				pim_inet4_dump("<group?>", grp->group_addr, +					       group_str, sizeof(group_str)); +				pim_time_timer_to_mmss( +					grp_retr_mmss, sizeof(grp_retr_mmss), +					grp->t_group_query_retransmit_timer); + + +				/* count group sources with retransmission state +				 */ +				for (ALL_LIST_ELEMENTS_RO( +					     grp->group_source_list, src_node, +					     src)) { +					if (src->source_query_retransmit_count +					    > 0) { +						++grp_retr_sources; +					} +				} + +				vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d\n", +					ifp->name, ifaddr_str, group_str, +					grp_retr_mmss, +					grp->group_specific_query_retransmit_count, +					grp_retr_sources); + +			} /* scan igmp groups */ +		}	 /* scan igmp sockets */ +	}		  /* scan interfaces */  }  static void igmp_show_sources(struct vty *vty)  { -  struct listnode  *ifnode; -  struct interface *ifp; -  time_t            now; - -  now = pim_time_monotonic_sec(); - -  vty_out (vty, -            "Interface Address         Group           Source          Timer Fwd Uptime  \n"); - -  /* scan interfaces */ -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { -    struct pim_interface *pim_ifp = ifp->info; -    struct listnode  *sock_node; -    struct igmp_sock *igmp; -     -    if (!pim_ifp) -      continue; -     -    /* scan igmp sockets */ -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      struct listnode   *grpnode; -      struct igmp_group *grp; - -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - -      /* scan igmp groups */ -      for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { -	char group_str[INET_ADDRSTRLEN]; -	struct listnode    *srcnode; -	struct igmp_source *src; - -	pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); -	 -	/* scan group sources */ -	for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { -	  char source_str[INET_ADDRSTRLEN]; -	  char mmss[10]; -	  char uptime[10]; - -	  pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str)); - -	  pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer); - -	  pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation); - -	  vty_out (vty, "%-9s %-15s %-15s %-15s %5s %3s %8s\n", -		  ifp->name, -		  ifaddr_str, -		  group_str, -		  source_str, -		  mmss, -		  IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" : "N", -		  uptime); -	   -	} /* scan group sources */ -      } /* scan igmp groups */ -    } /* scan igmp sockets */ -  } /* scan interfaces */ +	struct listnode *ifnode; +	struct interface *ifp; +	time_t now; + +	now = pim_time_monotonic_sec(); + +	vty_out(vty, +		"Interface Address         Group           Source          Timer Fwd Uptime  \n"); + +	/* scan interfaces */ +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { +		struct pim_interface *pim_ifp = ifp->info; +		struct listnode *sock_node; +		struct igmp_sock *igmp; + +		if (!pim_ifp) +			continue; + +		/* scan igmp sockets */ +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, +					  igmp)) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			struct listnode *grpnode; +			struct igmp_group *grp; + +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); + +			/* scan igmp groups */ +			for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, +						  grpnode, grp)) { +				char group_str[INET_ADDRSTRLEN]; +				struct listnode *srcnode; +				struct igmp_source *src; + +				pim_inet4_dump("<group?>", grp->group_addr, +					       group_str, sizeof(group_str)); + +				/* scan group sources */ +				for (ALL_LIST_ELEMENTS_RO( +					     grp->group_source_list, srcnode, +					     src)) { +					char source_str[INET_ADDRSTRLEN]; +					char mmss[10]; +					char uptime[10]; + +					pim_inet4_dump( +						"<source?>", src->source_addr, +						source_str, sizeof(source_str)); + +					pim_time_timer_to_mmss( +						mmss, sizeof(mmss), +						src->t_source_timer); + +					pim_time_uptime( +						uptime, sizeof(uptime), +						now - src->source_creation); + +					vty_out(vty, +						"%-9s %-15s %-15s %-15s %5s %3s %8s\n", +						ifp->name, ifaddr_str, +						group_str, source_str, mmss, +						IGMP_SOURCE_TEST_FORWARDING( +							src->source_flags) +							? "Y" +							: "N", +						uptime); + +				} /* scan group sources */ +			}	 /* scan igmp groups */ +		}		  /* scan igmp sockets */ +	}			  /* scan interfaces */  }  static void igmp_show_source_retransmission(struct vty *vty)  { -  struct listnode  *ifnode; -  struct interface *ifp; - -  vty_out (vty, -            "Interface Address         Group           Source          Counter\n"); - -  /* scan interfaces */ -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { -    struct pim_interface *pim_ifp = ifp->info; -    struct listnode  *sock_node; -    struct igmp_sock *igmp; -     -    if (!pim_ifp) -      continue; -     -    /* scan igmp sockets */ -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      struct listnode   *grpnode; -      struct igmp_group *grp; - -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - -      /* scan igmp groups */ -      for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { -	char group_str[INET_ADDRSTRLEN]; -	struct listnode    *srcnode; -	struct igmp_source *src; - -	pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str)); -	 -	/* scan group sources */ -	for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { -	  char source_str[INET_ADDRSTRLEN]; - -	  pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str)); - -	  vty_out (vty, "%-9s %-15s %-15s %-15s %7d\n", -		  ifp->name, -		  ifaddr_str, -		  group_str, -		  source_str, -		  src->source_query_retransmit_count); -	   -	} /* scan group sources */ -      } /* scan igmp groups */ -    } /* scan igmp sockets */ -  } /* scan interfaces */ +	struct listnode *ifnode; +	struct interface *ifp; + +	vty_out(vty, +		"Interface Address         Group           Source          Counter\n"); + +	/* scan interfaces */ +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { +		struct pim_interface *pim_ifp = ifp->info; +		struct listnode *sock_node; +		struct igmp_sock *igmp; + +		if (!pim_ifp) +			continue; + +		/* scan igmp sockets */ +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, +					  igmp)) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			struct listnode *grpnode; +			struct igmp_group *grp; + +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); + +			/* scan igmp groups */ +			for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, +						  grpnode, grp)) { +				char group_str[INET_ADDRSTRLEN]; +				struct listnode *srcnode; +				struct igmp_source *src; + +				pim_inet4_dump("<group?>", grp->group_addr, +					       group_str, sizeof(group_str)); + +				/* scan group sources */ +				for (ALL_LIST_ELEMENTS_RO( +					     grp->group_source_list, srcnode, +					     src)) { +					char source_str[INET_ADDRSTRLEN]; + +					pim_inet4_dump( +						"<source?>", src->source_addr, +						source_str, sizeof(source_str)); + +					vty_out(vty, +						"%-9s %-15s %-15s %-15s %7d\n", +						ifp->name, ifaddr_str, +						group_str, source_str, +						src->source_query_retransmit_count); + +				} /* scan group sources */ +			}	 /* scan igmp groups */ +		}		  /* scan igmp sockets */ +	}			  /* scan interfaces */  }  static void clear_igmp_interfaces()  { -  struct listnode  *ifnode; -  struct listnode  *ifnextnode; -  struct interface *ifp; +	struct listnode *ifnode; +	struct listnode *ifnextnode; +	struct interface *ifp; -  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { -    pim_if_addr_del_all_igmp(ifp); -  } +	for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, +			       ifp)) { +		pim_if_addr_del_all_igmp(ifp); +	} -  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { -    pim_if_addr_add_all(ifp); -  } +	for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, +			       ifp)) { +		pim_if_addr_add_all(ifp); +	}  }  static void clear_pim_interfaces()  { -  struct listnode  *ifnode; -  struct listnode  *ifnextnode; -  struct interface *ifp; +	struct listnode *ifnode; +	struct listnode *ifnextnode; +	struct interface *ifp; -  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { -    if (ifp->info) { -      pim_neighbor_delete_all(ifp, "interface cleared"); -    } -  } +	for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, +			       ifp)) { +		if (ifp->info) { +			pim_neighbor_delete_all(ifp, "interface cleared"); +		} +	}  }  static void clear_interfaces()  { -  clear_igmp_interfaces(); -  clear_pim_interfaces(); +	clear_igmp_interfaces(); +	clear_pim_interfaces();  }  DEFUN (clear_ip_interfaces, @@ -2600,9 +3052,9 @@ DEFUN (clear_ip_interfaces,         IP_STR         "Reset interfaces\n")  { -  clear_interfaces(); +	clear_interfaces(); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (clear_ip_igmp_interfaces, @@ -2613,47 +3065,51 @@ DEFUN (clear_ip_igmp_interfaces,         CLEAR_IP_IGMP_STR         "Reset IGMP interfaces\n")  { -  clear_igmp_interfaces(); +	clear_igmp_interfaces(); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  static void mroute_add_all()  { -  struct listnode    *node; -  struct channel_oil *c_oil; - -  for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { -    if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { -      /* just log warning */ -      char source_str[INET_ADDRSTRLEN]; -      char group_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -      pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -      zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", -                __FILE__, __PRETTY_FUNCTION__, -                source_str, group_str); -    } -  } +	struct listnode *node; +	struct channel_oil *c_oil; + +	for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { +		if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { +			/* just log warning */ +			char source_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, +				       source_str, sizeof(source_str)); +			pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", +				  __FILE__, __PRETTY_FUNCTION__, source_str, +				  group_str); +		} +	}  }  static void mroute_del_all()  { -  struct listnode    *node; -  struct channel_oil *c_oil; - -  for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { -    if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) { -      /* just log warning */ -      char source_str[INET_ADDRSTRLEN]; -      char group_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -      pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -      zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", -                __FILE__, __PRETTY_FUNCTION__, -                source_str, group_str); -    } -  } +	struct listnode *node; +	struct channel_oil *c_oil; + +	for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { +		if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) { +			/* just log warning */ +			char source_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, +				       source_str, sizeof(source_str)); +			pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", +				  __FILE__, __PRETTY_FUNCTION__, source_str, +				  group_str); +		} +	}  }  DEFUN (clear_ip_mroute, @@ -2663,10 +3119,10 @@ DEFUN (clear_ip_mroute,         IP_STR         "Reset multicast routes\n")  { -  mroute_del_all(); -  mroute_add_all(); +	mroute_del_all(); +	mroute_add_all(); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (clear_ip_pim_interfaces, @@ -2677,9 +3133,9 @@ DEFUN (clear_ip_pim_interfaces,         CLEAR_IP_PIM_STR         "Reset PIM interfaces\n")  { -  clear_pim_interfaces(); +	clear_pim_interfaces(); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (clear_ip_pim_interface_traffic, @@ -2691,34 +3147,33 @@ DEFUN (clear_ip_pim_interface_traffic,         "Reset PIM interfaces\n"         "Reset Protocol Packet counters\n")  { -  struct listnode  *ifnode = NULL; -  struct listnode  *ifnextnode = NULL; -  struct interface *ifp = NULL; -  struct pim_interface *pim_ifp = NULL; - -  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) -    { -      pim_ifp = ifp->info; - -      if (!pim_ifp) -        continue; - -      pim_ifp->pim_ifstat_hello_recv = 0; -      pim_ifp->pim_ifstat_hello_sent = 0; -      pim_ifp->pim_ifstat_join_recv = 0; -      pim_ifp->pim_ifstat_join_send = 0; -      pim_ifp->pim_ifstat_prune_recv = 0; -      pim_ifp->pim_ifstat_prune_send = 0; -      pim_ifp->pim_ifstat_reg_recv = 0; -      pim_ifp->pim_ifstat_reg_send = 0; -      pim_ifp->pim_ifstat_reg_stop_recv = 0; -      pim_ifp->pim_ifstat_reg_stop_send = 0; -      pim_ifp->pim_ifstat_assert_recv = 0; -      pim_ifp->pim_ifstat_assert_send = 0; - -    } +	struct listnode *ifnode = NULL; +	struct listnode *ifnextnode = NULL; +	struct interface *ifp = NULL; +	struct pim_interface *pim_ifp = NULL; + +	for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, +			       ifp)) { +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		pim_ifp->pim_ifstat_hello_recv = 0; +		pim_ifp->pim_ifstat_hello_sent = 0; +		pim_ifp->pim_ifstat_join_recv = 0; +		pim_ifp->pim_ifstat_join_send = 0; +		pim_ifp->pim_ifstat_prune_recv = 0; +		pim_ifp->pim_ifstat_prune_send = 0; +		pim_ifp->pim_ifstat_reg_recv = 0; +		pim_ifp->pim_ifstat_reg_send = 0; +		pim_ifp->pim_ifstat_reg_stop_recv = 0; +		pim_ifp->pim_ifstat_reg_stop_send = 0; +		pim_ifp->pim_ifstat_assert_recv = 0; +		pim_ifp->pim_ifstat_assert_send = 0; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (clear_ip_pim_oil, @@ -2729,9 +3184,9 @@ DEFUN (clear_ip_pim_oil,         CLEAR_IP_PIM_STR         "Rescan PIM OIL (output interface list)\n")  { -  pim_scan_oil(); +	pim_scan_oil(); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_igmp_interface, @@ -2745,16 +3200,16 @@ DEFUN (show_ip_igmp_interface,         "interface name\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  int idx = 0; +	u_char uj = use_json(argc, argv); +	int idx = 0; -  if (argv_find(argv, argc, "detail", &idx) || -      argv_find(argv, argc, "WORD", &idx)) -    igmp_show_interfaces_single(vty, argv[idx]->arg, uj); -  else -    igmp_show_interfaces(vty, uj); +	if (argv_find(argv, argc, "detail", &idx) +	    || argv_find(argv, argc, "WORD", &idx)) +		igmp_show_interfaces_single(vty, argv[idx]->arg, uj); +	else +		igmp_show_interfaces(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_igmp_join, @@ -2765,9 +3220,9 @@ DEFUN (show_ip_igmp_join,         IGMP_STR         "IGMP static join information\n")  { -  igmp_show_interface_join(vty); +	igmp_show_interface_join(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_igmp_groups, @@ -2779,10 +3234,10 @@ DEFUN (show_ip_igmp_groups,         IGMP_GROUP_STR         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  igmp_show_groups(vty, uj); +	u_char uj = use_json(argc, argv); +	igmp_show_groups(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_igmp_groups_retransmissions, @@ -2794,9 +3249,9 @@ DEFUN (show_ip_igmp_groups_retransmissions,         IGMP_GROUP_STR         "IGMP group retransmissions\n")  { -  igmp_show_group_retransmission(vty); +	igmp_show_group_retransmission(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_igmp_sources, @@ -2807,9 +3262,9 @@ DEFUN (show_ip_igmp_sources,         IGMP_STR         IGMP_SOURCE_STR)  { -  igmp_show_sources(vty); +	igmp_show_sources(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_igmp_sources_retransmissions, @@ -2821,9 +3276,9 @@ DEFUN (show_ip_igmp_sources_retransmissions,         IGMP_SOURCE_STR         "IGMP source retransmissions\n")  { -  igmp_show_source_retransmission(vty); +	igmp_show_source_retransmission(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_assert, @@ -2834,9 +3289,9 @@ DEFUN (show_ip_pim_assert,         PIM_STR         "PIM interface assert\n")  { -  pim_show_assert(vty); +	pim_show_assert(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_assert_internal, @@ -2847,9 +3302,9 @@ DEFUN (show_ip_pim_assert_internal,         PIM_STR         "PIM interface internal assert state\n")  { -  pim_show_assert_internal(vty); +	pim_show_assert_internal(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_assert_metric, @@ -2860,9 +3315,9 @@ DEFUN (show_ip_pim_assert_metric,         PIM_STR         "PIM interface assert metric\n")  { -  pim_show_assert_metric(vty); +	pim_show_assert_metric(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_assert_winner_metric, @@ -2873,9 +3328,9 @@ DEFUN (show_ip_pim_assert_winner_metric,         PIM_STR         "PIM interface assert winner metric\n")  { -  pim_show_assert_winner_metric(vty); +	pim_show_assert_winner_metric(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_interface, @@ -2889,17 +3344,17 @@ DEFUN (show_ip_pim_interface,         "interface name\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  int idx = 0; +	u_char uj = use_json(argc, argv); +	int idx = 0; -  if (argv_find(argv, argc, "WORD", &idx) || -      argv_find(argv, argc, "detail", &idx)) -    pim_show_interfaces_single(vty, argv[idx]->arg, uj); +	if (argv_find(argv, argc, "WORD", &idx) +	    || argv_find(argv, argc, "detail", &idx)) +		pim_show_interfaces_single(vty, argv[idx]->arg, uj); -  else -    pim_show_interfaces(vty, uj); +	else +		pim_show_interfaces(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_join, @@ -2911,10 +3366,10 @@ DEFUN (show_ip_pim_join,         "PIM interface join information\n"         JSON_STR)  { -  u_char uj = use_json(argc, argv); -  pim_show_join(vty, uj); +	u_char uj = use_json(argc, argv); +	pim_show_join(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_local_membership, @@ -2926,10 +3381,10 @@ DEFUN (show_ip_pim_local_membership,         "PIM interface local-membership\n"         JSON_STR)  { -  u_char uj = use_json(argc, argv); -  pim_show_membership(vty, uj); +	u_char uj = use_json(argc, argv); +	pim_show_membership(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_neighbor, @@ -2943,16 +3398,16 @@ DEFUN (show_ip_pim_neighbor,         "Name of interface or neighbor\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  int idx = 0; +	u_char uj = use_json(argc, argv); +	int idx = 0; -  if (argv_find(argv, argc, "detail", &idx) || -      argv_find(argv, argc, "WORD", &idx)) -    pim_show_neighbors_single(vty, argv[idx]->arg, uj); -  else -    pim_show_neighbors(vty, uj); +	if (argv_find(argv, argc, "detail", &idx) +	    || argv_find(argv, argc, "WORD", &idx)) +		pim_show_neighbors_single(vty, argv[idx]->arg, uj); +	else +		pim_show_neighbors(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_secondary, @@ -2963,9 +3418,9 @@ DEFUN (show_ip_pim_secondary,         PIM_STR         "PIM neighbor addresses\n")  { -  pim_show_neighbors_secondary(vty); +	pim_show_neighbors_secondary(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_state, @@ -2979,23 +3434,21 @@ DEFUN (show_ip_pim_state,         "Multicast address\n"         "JavaScript Object Notation\n")  { -  const char *src_or_group = NULL; -  const char *group = NULL; -  u_char uj = use_json(argc, argv); -  if (uj) -    argc--; +	const char *src_or_group = NULL; +	const char *group = NULL; +	u_char uj = use_json(argc, argv); +	if (uj) +		argc--; -  if (argc == 6) -    { -      src_or_group = argv[4]->arg; -      group = argv[5]->arg; -    } -  else if (argc == 5) -    src_or_group = argv[4]->arg; +	if (argc == 6) { +		src_or_group = argv[4]->arg; +		group = argv[5]->arg; +	} else if (argc == 5) +		src_or_group = argv[4]->arg; -  pim_show_state(vty, src_or_group, group, uj); +	pim_show_state(vty, src_or_group, group, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_upstream, @@ -3007,10 +3460,10 @@ DEFUN (show_ip_pim_upstream,         "PIM upstream information\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  pim_show_upstream(vty, uj); +	u_char uj = use_json(argc, argv); +	pim_show_upstream(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_upstream_join_desired, @@ -3022,10 +3475,10 @@ DEFUN (show_ip_pim_upstream_join_desired,         "PIM upstream join-desired\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  pim_show_join_desired(vty, uj); +	u_char uj = use_json(argc, argv); +	pim_show_join_desired(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_upstream_rpf, @@ -3037,10 +3490,10 @@ DEFUN (show_ip_pim_upstream_rpf,         "PIM upstream source rpf\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  pim_show_upstream_rpf(vty, uj); +	u_char uj = use_json(argc, argv); +	pim_show_upstream_rpf(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_rp, @@ -3052,10 +3505,10 @@ DEFUN (show_ip_pim_rp,         "PIM RP information\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  pim_rp_show_information (vty, uj); +	u_char uj = use_json(argc, argv); +	pim_rp_show_information(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_rpf, @@ -3067,10 +3520,10 @@ DEFUN (show_ip_pim_rpf,         "PIM cached source rpf information\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  pim_show_rpf(vty, uj); +	u_char uj = use_json(argc, argv); +	pim_show_rpf(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_nexthop, @@ -3081,9 +3534,9 @@ DEFUN (show_ip_pim_nexthop,         PIM_STR         "PIM cached nexthop rpf information\n")  { -  pim_show_nexthop (vty); +	pim_show_nexthop(vty); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_nexthop_lookup, @@ -3096,75 +3549,70 @@ DEFUN (show_ip_pim_nexthop_lookup,         "Source/RP address\n"         "Multicast Group address\n")  { -  struct pim_nexthop_cache pnc; -  struct prefix nht_p; -  int result = 0; -  struct in_addr src_addr, grp_addr; -  struct in_addr vif_source; -  const char *addr_str, *addr_str1; -  struct prefix grp; -  struct pim_nexthop nexthop; -  char nexthop_addr_str[PREFIX_STRLEN]; -  char grp_str[PREFIX_STRLEN]; - -  addr_str = argv[4]->arg; -  result = inet_pton (AF_INET, addr_str, &src_addr); -  if (result <= 0) -    { -      vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", -               addr_str, errno, safe_strerror(errno)); -      return CMD_WARNING; -    } - -  if (pim_is_group_224_4 (src_addr)) -    { -      vty_out (vty, "Invalid argument. Expected Valid Source Address.\n"); -      return CMD_WARNING; -    } - -  addr_str1 = argv[5]->arg; -  result = inet_pton (AF_INET, addr_str1, &grp_addr); -  if (result <= 0) -    { -      vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", -               addr_str, errno, safe_strerror(errno)); -      return CMD_WARNING; -    } - -  if (!pim_is_group_224_4 (grp_addr)) -    { -      vty_out (vty, -                 "Invalid argument. Expected Valid Multicast Group Address.\n"); -      return CMD_WARNING; -    } - -  if (!pim_rp_set_upstream_addr (&vif_source, src_addr, grp_addr)) -    return CMD_SUCCESS; - -  memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -  nht_p.family = AF_INET; -  nht_p.prefixlen = IPV4_MAX_BITLEN; -  nht_p.u.prefix4 = vif_source; -  grp.family = AF_INET; -  grp.prefixlen = IPV4_MAX_BITLEN; -  grp.u.prefix4 = grp_addr; -  memset (&nexthop, 0, sizeof (nexthop)); - -  if ((pim_find_or_track_nexthop (&nht_p, NULL, NULL, &pnc)) == 1) -    { -      //Compute PIM RPF using Cached nexthop -      pim_ecmp_nexthop_search (&pnc, &nexthop, &nht_p, &grp, 0); -    } -  else -    pim_ecmp_nexthop_lookup (&nexthop, vif_source, &nht_p, &grp, 0); - -  pim_addr_dump ("<grp?>", &grp, grp_str, sizeof (grp_str)); -  pim_addr_dump ("<nexthop?>", &nexthop.mrib_nexthop_addr, -                 nexthop_addr_str, sizeof (nexthop_addr_str)); -  vty_out (vty, "Group %s --- Nexthop %s Interface %s \n", grp_str, -           nexthop_addr_str, nexthop.interface->name); - -  return CMD_SUCCESS; +	struct pim_nexthop_cache pnc; +	struct prefix nht_p; +	int result = 0; +	struct in_addr src_addr, grp_addr; +	struct in_addr vif_source; +	const char *addr_str, *addr_str1; +	struct prefix grp; +	struct pim_nexthop nexthop; +	char nexthop_addr_str[PREFIX_STRLEN]; +	char grp_str[PREFIX_STRLEN]; + +	addr_str = argv[4]->arg; +	result = inet_pton(AF_INET, addr_str, &src_addr); +	if (result <= 0) { +		vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING; +	} + +	if (pim_is_group_224_4(src_addr)) { +		vty_out(vty, +			"Invalid argument. Expected Valid Source Address.\n"); +		return CMD_WARNING; +	} + +	addr_str1 = argv[5]->arg; +	result = inet_pton(AF_INET, addr_str1, &grp_addr); +	if (result <= 0) { +		vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING; +	} + +	if (!pim_is_group_224_4(grp_addr)) { +		vty_out(vty, +			"Invalid argument. Expected Valid Multicast Group Address.\n"); +		return CMD_WARNING; +	} + +	if (!pim_rp_set_upstream_addr(&vif_source, src_addr, grp_addr)) +		return CMD_SUCCESS; + +	memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +	nht_p.family = AF_INET; +	nht_p.prefixlen = IPV4_MAX_BITLEN; +	nht_p.u.prefix4 = vif_source; +	grp.family = AF_INET; +	grp.prefixlen = IPV4_MAX_BITLEN; +	grp.u.prefix4 = grp_addr; +	memset(&nexthop, 0, sizeof(nexthop)); + +	if ((pim_find_or_track_nexthop(&nht_p, NULL, NULL, &pnc)) == 1) { +		// Compute PIM RPF using Cached nexthop +		pim_ecmp_nexthop_search(&pnc, &nexthop, &nht_p, &grp, 0); +	} else +		pim_ecmp_nexthop_lookup(&nexthop, vif_source, &nht_p, &grp, 0); + +	pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str)); +	pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, +		      nexthop_addr_str, sizeof(nexthop_addr_str)); +	vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", grp_str, +		nexthop_addr_str, nexthop.interface->name); + +	return CMD_SUCCESS;  }  DEFUN (show_ip_pim_interface_traffic, @@ -3178,61 +3626,56 @@ DEFUN (show_ip_pim_interface_traffic,         "Interface name\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json (argc, argv); -  int idx = 0; +	u_char uj = use_json(argc, argv); +	int idx = 0; -  if (argv_find(argv, argc, "WORD", &idx)) -    pim_show_interface_traffic_single (vty, argv[idx]->arg, uj); -  else -    pim_show_interface_traffic (vty, uj); +	if (argv_find(argv, argc, "WORD", &idx)) +		pim_show_interface_traffic_single(vty, argv[idx]->arg, uj); +	else +		pim_show_interface_traffic(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  static void show_multicast_interfaces(struct vty *vty)  { -  struct listnode  *node; -  struct interface *ifp; - -  vty_out (vty, "\n"); -   -  vty_out (vty, -            "Interface Address         ifi Vif  PktsIn PktsOut    BytesIn   BytesOut\n"); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { -    struct pim_interface *pim_ifp; -    struct in_addr ifaddr; -    struct sioc_vif_req vreq; - -    pim_ifp = ifp->info; -     -    if (!pim_ifp) -      continue; - -    memset(&vreq, 0, sizeof(vreq)); -    vreq.vifi = pim_ifp->mroute_vif_index; - -    if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) { -      zlog_warn("ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s\n", -		(unsigned long)SIOCGETVIFCNT, -		ifp->name, -		pim_ifp->mroute_vif_index, -		errno, -		safe_strerror(errno)); -    } - -    ifaddr = pim_ifp->primary_address; - -    vty_out (vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu\n", -	    ifp->name, -	    inet_ntoa(ifaddr), -	    ifp->ifindex, -	    pim_ifp->mroute_vif_index, -	    (unsigned long) vreq.icount, -	    (unsigned long) vreq.ocount, -	    (unsigned long) vreq.ibytes, -	    (unsigned long)vreq.obytes); -  } +	struct listnode *node; +	struct interface *ifp; + +	vty_out(vty, "\n"); + +	vty_out(vty, +		"Interface Address         ifi Vif  PktsIn PktsOut    BytesIn   BytesOut\n"); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		struct pim_interface *pim_ifp; +		struct in_addr ifaddr; +		struct sioc_vif_req vreq; + +		pim_ifp = ifp->info; + +		if (!pim_ifp) +			continue; + +		memset(&vreq, 0, sizeof(vreq)); +		vreq.vifi = pim_ifp->mroute_vif_index; + +		if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) { +			zlog_warn( +				"ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s\n", +				(unsigned long)SIOCGETVIFCNT, ifp->name, +				pim_ifp->mroute_vif_index, errno, +				safe_strerror(errno)); +		} + +		ifaddr = pim_ifp->primary_address; + +		vty_out(vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu\n", +			ifp->name, inet_ntoa(ifaddr), ifp->ifindex, +			pim_ifp->mroute_vif_index, (unsigned long)vreq.icount, +			(unsigned long)vreq.ocount, (unsigned long)vreq.ibytes, +			(unsigned long)vreq.obytes); +	}  }  DEFUN (show_ip_multicast, @@ -3242,327 +3685,364 @@ DEFUN (show_ip_multicast,         IP_STR         "Multicast global information\n")  { -  time_t now = pim_time_monotonic_sec(); +	time_t now = pim_time_monotonic_sec(); -  char uptime[10]; +	char uptime[10]; + +	vty_out(vty, "Mroute socket descriptor: %d\n", qpim_mroute_socket_fd); -  vty_out (vty, "Mroute socket descriptor: %d\n", -          qpim_mroute_socket_fd); +	pim_time_uptime(uptime, sizeof(uptime), +			now - qpim_mroute_socket_creation); +	vty_out(vty, "Mroute socket uptime: %s\n", uptime); -  pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation); -  vty_out (vty, "Mroute socket uptime: %s\n", -          uptime); +	vty_out(vty, "\n"); -  vty_out (vty, "\n"); +	pim_zebra_zclient_update(vty); +	pim_zlookup_show_ip_multicast(vty); -  pim_zebra_zclient_update (vty); -  pim_zlookup_show_ip_multicast (vty); +	vty_out(vty, "\n"); +	vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS); -  vty_out (vty, "\n"); -  vty_out (vty, "Maximum highest VifIndex: %d\n", -	  PIM_MAX_USABLE_VIFS); +	vty_out(vty, "\n"); +	vty_out(vty, "Upstream Join Timer: %d secs\n", qpim_t_periodic); +	vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME); +	vty_out(vty, "PIM ECMP: %s\n", qpim_ecmp_enable ? "Enable" : "Disable"); +	vty_out(vty, "PIM ECMP Rebalance: %s\n", +		qpim_ecmp_rebalance_enable ? "Enable" : "Disable"); -  vty_out (vty, "\n"); -  vty_out (vty, "Upstream Join Timer: %d secs\n", -           qpim_t_periodic); -  vty_out (vty, "Join/Prune Holdtime: %d secs\n", -           PIM_JP_HOLDTIME); -  vty_out (vty, "PIM ECMP: %s\n", -           qpim_ecmp_enable ? "Enable" : "Disable"); -  vty_out (vty, "PIM ECMP Rebalance: %s\n", -           qpim_ecmp_rebalance_enable ? "Enable" : "Disable"); +	vty_out(vty, "\n"); -  vty_out (vty, "\n"); +	show_rpf_refresh_stats(vty, now, NULL); -  show_rpf_refresh_stats(vty, now, NULL); +	vty_out(vty, "\n"); -  vty_out (vty, "\n"); +	show_scan_oil_stats(vty, now); -  show_scan_oil_stats(vty, now); +	show_multicast_interfaces(vty); -  show_multicast_interfaces(vty); -   -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  static void show_mroute(struct vty *vty, u_char uj)  { -  struct listnode    *node; -  struct channel_oil *c_oil; -  struct static_route *s_route; -  time_t              now; -  json_object *json = NULL; -  json_object *json_group = NULL; -  json_object *json_source = NULL; -  json_object *json_oil = NULL; -  json_object *json_ifp_out = NULL; -  int found_oif = 0; -  int first = 1; -  char grp_str[INET_ADDRSTRLEN]; -  char src_str[INET_ADDRSTRLEN]; -  char in_ifname[INTERFACE_NAMSIZ+1]; -  char out_ifname[INTERFACE_NAMSIZ+1]; -  int oif_vif_index; -  struct interface *ifp_in; -  char proto[100]; - -  if (uj) { -    json = json_object_new_object(); -  } else { -    vty_out (vty, -              "Source          Group           Proto  Input      Output     TTL  Uptime\n"); -  } - -  now = pim_time_monotonic_sec(); - -  /* print list of PIM and IGMP routes */ -  for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { -    found_oif = 0; -    first = 1; -    if (!c_oil->installed && !uj) -      continue; - -    pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); -    pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); -    ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - -    if (ifp_in) -      strcpy(in_ifname, ifp_in->name); -    else -      strcpy(in_ifname, "<iif?>"); - -    if (uj) { - -      /* Find the group, create it if it doesn't exist */ -      json_object_object_get_ex(json, grp_str, &json_group); - -      if (!json_group) { -        json_group = json_object_new_object(); -        json_object_object_add(json, grp_str, json_group); -      } - -      /* Find the source nested under the group, create it if it doesn't exist */ -      json_object_object_get_ex(json_group, src_str, &json_source); - -      if (!json_source) { -        json_source = json_object_new_object(); -        json_object_object_add(json_group, src_str, json_source); -      } - -      /* Find the inbound interface nested under the source, create it if it doesn't exist */ -      json_object_int_add(json_source, "installed", c_oil->installed); -      json_object_int_add(json_source, "refCount", c_oil->oil_ref_count); -      json_object_int_add(json_source, "oilSize", c_oil->oil_size); -      json_object_int_add(json_source, "OilInheritedRescan", c_oil->oil_inherited_rescan); -      json_object_string_add(json_source, "iif", in_ifname); -      json_oil = NULL; -    } - -    for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { -      struct interface *ifp_out; -      char oif_uptime[10]; -      int ttl; - -      ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; -      if (ttl < 1) -	continue; - -      ifp_out = pim_if_find_by_vif_index(oif_vif_index); -      pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); -      found_oif = 1; - -      if (ifp_out) -        strcpy(out_ifname, ifp_out->name); -      else -        strcpy(out_ifname, "<oif?>"); - -      if (uj) { -        json_ifp_out = json_object_new_object(); -        json_object_string_add(json_ifp_out, "source", src_str); -        json_object_string_add(json_ifp_out, "group", grp_str); - -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) -          json_object_boolean_true_add(json_ifp_out, "protocolPim"); - -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) -          json_object_boolean_true_add(json_ifp_out, "protocolIgmp"); - -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) -          json_object_boolean_true_add(json_ifp_out, "protocolSource"); - -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) -          json_object_boolean_true_add(json_ifp_out, "protocolInherited"); - -        json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); -        json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent); -        json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); -        json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); -        json_object_int_add(json_ifp_out, "ttl", ttl); -        json_object_string_add(json_ifp_out, "upTime", oif_uptime); -        if (!json_oil) { -          json_oil = json_object_new_object(); -          json_object_object_add(json_source, "oil", json_oil); -        } -        json_object_object_add(json_oil, out_ifname, json_ifp_out); -      } else { -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { -          strcpy(proto, "PIM"); -        } - -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) { -          strcpy(proto, "IGMP"); -        } - -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { -          strcpy(proto, "SRC"); -        } - -        if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) { -          strcpy(proto, "STAR"); -        } - -        vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", -                src_str, -                grp_str, -                proto, -                in_ifname, -                out_ifname, -                ttl, -                oif_uptime); - -        if (first) -	  { -	    src_str[0] = '\0'; -	    grp_str[0] = '\0'; -	    in_ifname[0] = '\0'; -	    first = 0; -	  } -      } -    } - -    if (!uj && !found_oif) { -      vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", -              src_str, -              grp_str, -              "none", -              in_ifname, -              "none", -              0, -              "--:--:--"); -    } -  } - -  /* Print list of static routes */ -  for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { -    first = 1; - -    if (!s_route->c_oil.installed) -      continue; - -    pim_inet4_dump("<group?>", s_route->group, grp_str, sizeof(grp_str)); -    pim_inet4_dump("<source?>", s_route->source, src_str, sizeof(src_str)); -    ifp_in  = pim_if_find_by_vif_index(s_route->iif); -    found_oif = 0; - -    if (ifp_in) -      strcpy(in_ifname, ifp_in->name); -    else -      strcpy(in_ifname, "<iif?>"); - -    if (uj) { - -      /* Find the group, create it if it doesn't exist */ -      json_object_object_get_ex(json, grp_str, &json_group); - -      if (!json_group) { -        json_group = json_object_new_object(); -        json_object_object_add(json, grp_str, json_group); -      } - -      /* Find the source nested under the group, create it if it doesn't exist */ -      json_object_object_get_ex(json_group, src_str, &json_source); - -      if (!json_source) { -        json_source = json_object_new_object(); -        json_object_object_add(json_group, src_str, json_source); -      } - -      json_object_string_add(json_source, "iif", in_ifname); -      json_oil = NULL; -    } else { -      strcpy(proto, "STATIC"); -    } - -    for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { -      struct interface *ifp_out; -      char oif_uptime[10]; -      int ttl; - -      ttl = s_route->oif_ttls[oif_vif_index]; -      if (ttl < 1) -         continue; - -      ifp_out = pim_if_find_by_vif_index(oif_vif_index); -      pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]); -      found_oif = 1; - -      if (ifp_out) -        strcpy(out_ifname, ifp_out->name); -      else -        strcpy(out_ifname, "<oif?>"); - -      if (uj) { -        json_ifp_out = json_object_new_object(); -        json_object_string_add(json_ifp_out, "source", src_str); -        json_object_string_add(json_ifp_out, "group", grp_str); -        json_object_boolean_true_add(json_ifp_out, "protocolStatic"); -        json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); -        json_object_int_add(json_ifp_out, "iVifI", s_route->c_oil.oil.mfcc_parent); -        json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); -        json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); -        json_object_int_add(json_ifp_out, "ttl", ttl); -        json_object_string_add(json_ifp_out, "upTime", oif_uptime); -        if (!json_oil) { -          json_oil = json_object_new_object(); -          json_object_object_add(json_source, "oil", json_oil); -        } -        json_object_object_add(json_oil, out_ifname, json_ifp_out); -      } else { -        vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", -                src_str, -                grp_str, -                proto, -                in_ifname, -                out_ifname, -                ttl, -                oif_uptime); -	if (first) -          { -	    src_str[0] = '\0'; -	    grp_str[0] = '\0'; -	    in_ifname[0] = '\0'; -	    first = 0; -	  } -      } -    } - -    if (!uj && !found_oif) { -        vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", -                src_str, -                grp_str, -                proto, -                in_ifname, -                "none", -                0, -                "--:--:--"); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	struct listnode *node; +	struct channel_oil *c_oil; +	struct static_route *s_route; +	time_t now; +	json_object *json = NULL; +	json_object *json_group = NULL; +	json_object *json_source = NULL; +	json_object *json_oil = NULL; +	json_object *json_ifp_out = NULL; +	int found_oif = 0; +	int first = 1; +	char grp_str[INET_ADDRSTRLEN]; +	char src_str[INET_ADDRSTRLEN]; +	char in_ifname[INTERFACE_NAMSIZ + 1]; +	char out_ifname[INTERFACE_NAMSIZ + 1]; +	int oif_vif_index; +	struct interface *ifp_in; +	char proto[100]; + +	if (uj) { +		json = json_object_new_object(); +	} else { +		vty_out(vty, +			"Source          Group           Proto  Input      Output     TTL  Uptime\n"); +	} + +	now = pim_time_monotonic_sec(); + +	/* print list of PIM and IGMP routes */ +	for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { +		found_oif = 0; +		first = 1; +		if (!c_oil->installed && !uj) +			continue; + +		pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, +			       sizeof(grp_str)); +		pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, +			       sizeof(src_str)); +		ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + +		if (ifp_in) +			strcpy(in_ifname, ifp_in->name); +		else +			strcpy(in_ifname, "<iif?>"); + +		if (uj) { + +			/* Find the group, create it if it doesn't exist */ +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			/* Find the source nested under the group, create it if +			 * it doesn't exist */ +			json_object_object_get_ex(json_group, src_str, +						  &json_source); + +			if (!json_source) { +				json_source = json_object_new_object(); +				json_object_object_add(json_group, src_str, +						       json_source); +			} + +			/* Find the inbound interface nested under the source, +			 * create it if it doesn't exist */ +			json_object_int_add(json_source, "installed", +					    c_oil->installed); +			json_object_int_add(json_source, "refCount", +					    c_oil->oil_ref_count); +			json_object_int_add(json_source, "oilSize", +					    c_oil->oil_size); +			json_object_int_add(json_source, "OilInheritedRescan", +					    c_oil->oil_inherited_rescan); +			json_object_string_add(json_source, "iif", in_ifname); +			json_oil = NULL; +		} + +		for (oif_vif_index = 0; oif_vif_index < MAXVIFS; +		     ++oif_vif_index) { +			struct interface *ifp_out; +			char oif_uptime[10]; +			int ttl; + +			ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; +			if (ttl < 1) +				continue; + +			ifp_out = pim_if_find_by_vif_index(oif_vif_index); +			pim_time_uptime( +				oif_uptime, sizeof(oif_uptime), +				now - c_oil->oif_creation[oif_vif_index]); +			found_oif = 1; + +			if (ifp_out) +				strcpy(out_ifname, ifp_out->name); +			else +				strcpy(out_ifname, "<oif?>"); + +			if (uj) { +				json_ifp_out = json_object_new_object(); +				json_object_string_add(json_ifp_out, "source", +						       src_str); +				json_object_string_add(json_ifp_out, "group", +						       grp_str); + +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_PIM) +					json_object_boolean_true_add( +						json_ifp_out, "protocolPim"); + +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_IGMP) +					json_object_boolean_true_add( +						json_ifp_out, "protocolIgmp"); + +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_SOURCE) +					json_object_boolean_true_add( +						json_ifp_out, "protocolSource"); + +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_STAR) +					json_object_boolean_true_add( +						json_ifp_out, +						"protocolInherited"); + +				json_object_string_add(json_ifp_out, +						       "inboundInterface", +						       in_ifname); +				json_object_int_add(json_ifp_out, "iVifI", +						    c_oil->oil.mfcc_parent); +				json_object_string_add(json_ifp_out, +						       "outboundInterface", +						       out_ifname); +				json_object_int_add(json_ifp_out, "oVifI", +						    oif_vif_index); +				json_object_int_add(json_ifp_out, "ttl", ttl); +				json_object_string_add(json_ifp_out, "upTime", +						       oif_uptime); +				if (!json_oil) { +					json_oil = json_object_new_object(); +					json_object_object_add(json_source, +							       "oil", json_oil); +				} +				json_object_object_add(json_oil, out_ifname, +						       json_ifp_out); +			} else { +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_PIM) { +					strcpy(proto, "PIM"); +				} + +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_IGMP) { +					strcpy(proto, "IGMP"); +				} + +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_SOURCE) { +					strcpy(proto, "SRC"); +				} + +				if (c_oil->oif_flags[oif_vif_index] +				    & PIM_OIF_FLAG_PROTO_STAR) { +					strcpy(proto, "STAR"); +				} + +				vty_out(vty, +					"%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", +					src_str, grp_str, proto, in_ifname, +					out_ifname, ttl, oif_uptime); + +				if (first) { +					src_str[0] = '\0'; +					grp_str[0] = '\0'; +					in_ifname[0] = '\0'; +					first = 0; +				} +			} +		} + +		if (!uj && !found_oif) { +			vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", +				src_str, grp_str, "none", in_ifname, "none", 0, +				"--:--:--"); +		} +	} + +	/* Print list of static routes */ +	for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { +		first = 1; + +		if (!s_route->c_oil.installed) +			continue; + +		pim_inet4_dump("<group?>", s_route->group, grp_str, +			       sizeof(grp_str)); +		pim_inet4_dump("<source?>", s_route->source, src_str, +			       sizeof(src_str)); +		ifp_in = pim_if_find_by_vif_index(s_route->iif); +		found_oif = 0; + +		if (ifp_in) +			strcpy(in_ifname, ifp_in->name); +		else +			strcpy(in_ifname, "<iif?>"); + +		if (uj) { + +			/* Find the group, create it if it doesn't exist */ +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			/* Find the source nested under the group, create it if +			 * it doesn't exist */ +			json_object_object_get_ex(json_group, src_str, +						  &json_source); + +			if (!json_source) { +				json_source = json_object_new_object(); +				json_object_object_add(json_group, src_str, +						       json_source); +			} + +			json_object_string_add(json_source, "iif", in_ifname); +			json_oil = NULL; +		} else { +			strcpy(proto, "STATIC"); +		} + +		for (oif_vif_index = 0; oif_vif_index < MAXVIFS; +		     ++oif_vif_index) { +			struct interface *ifp_out; +			char oif_uptime[10]; +			int ttl; + +			ttl = s_route->oif_ttls[oif_vif_index]; +			if (ttl < 1) +				continue; + +			ifp_out = pim_if_find_by_vif_index(oif_vif_index); +			pim_time_uptime( +				oif_uptime, sizeof(oif_uptime), +				now +					- s_route->c_oil +						  .oif_creation[oif_vif_index]); +			found_oif = 1; + +			if (ifp_out) +				strcpy(out_ifname, ifp_out->name); +			else +				strcpy(out_ifname, "<oif?>"); + +			if (uj) { +				json_ifp_out = json_object_new_object(); +				json_object_string_add(json_ifp_out, "source", +						       src_str); +				json_object_string_add(json_ifp_out, "group", +						       grp_str); +				json_object_boolean_true_add(json_ifp_out, +							     "protocolStatic"); +				json_object_string_add(json_ifp_out, +						       "inboundInterface", +						       in_ifname); +				json_object_int_add( +					json_ifp_out, "iVifI", +					s_route->c_oil.oil.mfcc_parent); +				json_object_string_add(json_ifp_out, +						       "outboundInterface", +						       out_ifname); +				json_object_int_add(json_ifp_out, "oVifI", +						    oif_vif_index); +				json_object_int_add(json_ifp_out, "ttl", ttl); +				json_object_string_add(json_ifp_out, "upTime", +						       oif_uptime); +				if (!json_oil) { +					json_oil = json_object_new_object(); +					json_object_object_add(json_source, +							       "oil", json_oil); +				} +				json_object_object_add(json_oil, out_ifname, +						       json_ifp_out); +			} else { +				vty_out(vty, +					"%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", +					src_str, grp_str, proto, in_ifname, +					out_ifname, ttl, oif_uptime); +				if (first) { +					src_str[0] = '\0'; +					grp_str[0] = '\0'; +					in_ifname[0] = '\0'; +					first = 0; +				} +			} +		} + +		if (!uj && !found_oif) { +			vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n", +				src_str, grp_str, proto, in_ifname, "none", 0, +				"--:--:--"); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  DEFUN (show_ip_mroute, @@ -3573,65 +4053,63 @@ DEFUN (show_ip_mroute,         MROUTE_STR         JSON_STR)  { -  u_char uj = use_json(argc, argv); -  show_mroute(vty, uj); -  return CMD_SUCCESS; +	u_char uj = use_json(argc, argv); +	show_mroute(vty, uj); +	return CMD_SUCCESS;  }  static void show_mroute_count(struct vty *vty)  { -  struct listnode    *node; -  struct channel_oil *c_oil; -  struct static_route *s_route; +	struct listnode *node; +	struct channel_oil *c_oil; +	struct static_route *s_route; -  vty_out (vty, "\n"); -   -  vty_out (vty, -            "Source          Group           LastUsed Packets Bytes WrongIf  \n"); +	vty_out(vty, "\n"); -  /* Print PIM and IGMP route counts */ -  for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { -    char group_str[INET_ADDRSTRLEN];  -    char source_str[INET_ADDRSTRLEN]; +	vty_out(vty, +		"Source          Group           LastUsed Packets Bytes WrongIf  \n"); -    if (!c_oil->installed) -      continue; +	/* Print PIM and IGMP route counts */ +	for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; -    pim_mroute_update_counters (c_oil); +		if (!c_oil->installed) +			continue; -    pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); +		pim_mroute_update_counters(c_oil); -    vty_out (vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", -	    source_str, -	    group_str, -	    c_oil->cc.lastused/100, -	    c_oil->cc.pktcnt, -	    c_oil->cc.bytecnt, -	    c_oil->cc.wrong_if); -  } +		pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, +			       sizeof(source_str)); -   /* Print static route counts */ -  for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; +		vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", +			source_str, group_str, c_oil->cc.lastused / 100, +			c_oil->cc.pktcnt, c_oil->cc.bytecnt, +			c_oil->cc.wrong_if); +	} + +	/* Print static route counts */ +	for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; -    if (!s_route->c_oil.installed) -      continue; +		if (!s_route->c_oil.installed) +			continue; -    pim_mroute_update_counters (&s_route->c_oil); +		pim_mroute_update_counters(&s_route->c_oil); -    pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); +		pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, +			       group_str, sizeof(group_str)); +		pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, +			       source_str, sizeof(source_str)); -    vty_out (vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", -       source_str, -       group_str, -       s_route->c_oil.cc.lastused, -       s_route->c_oil.cc.pktcnt, -       s_route->c_oil.cc.bytecnt, -       s_route->c_oil.cc.wrong_if); -  } +		vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", +			source_str, group_str, s_route->c_oil.cc.lastused, +			s_route->c_oil.cc.pktcnt, s_route->c_oil.cc.bytecnt, +			s_route->c_oil.cc.wrong_if); +	}  }  DEFUN (show_ip_mroute_count, @@ -3642,8 +4120,8 @@ DEFUN (show_ip_mroute_count,         MROUTE_STR         "Route and packet count data\n")  { -  show_mroute_count(vty); -  return CMD_SUCCESS; +	show_mroute_count(vty); +	return CMD_SUCCESS;  }  DEFUN (show_ip_rib, @@ -3654,83 +4132,82 @@ DEFUN (show_ip_rib,         RIB_STR         "Unicast address\n")  { -  int idx_ipv4 = 3; -  struct in_addr addr; -  const char *addr_str; -  struct pim_nexthop nexthop; -  char nexthop_addr_str[PREFIX_STRLEN]; -  int result; - -  memset (&nexthop, 0, sizeof (nexthop)); -  addr_str = argv[idx_ipv4]->arg; -  result = inet_pton(AF_INET, addr_str, &addr); -  if (result <= 0) { -    vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", -	    addr_str, errno, safe_strerror(errno)); -    return CMD_WARNING; -  } +	int idx_ipv4 = 3; +	struct in_addr addr; +	const char *addr_str; +	struct pim_nexthop nexthop; +	char nexthop_addr_str[PREFIX_STRLEN]; +	int result; + +	memset(&nexthop, 0, sizeof(nexthop)); +	addr_str = argv[idx_ipv4]->arg; +	result = inet_pton(AF_INET, addr_str, &addr); +	if (result <= 0) { +		vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING; +	} -  if (pim_nexthop_lookup(&nexthop, addr, 0)) { -    vty_out (vty, "Failure querying RIB nexthop for unicast address %s\n", -	    addr_str); -    return CMD_WARNING; -  } +	if (pim_nexthop_lookup(&nexthop, addr, 0)) { +		vty_out(vty, +			"Failure querying RIB nexthop for unicast address %s\n", +			addr_str); +		return CMD_WARNING; +	} -  vty_out (vty, -            "Address         NextHop         Interface Metric Preference\n"); +	vty_out(vty, +		"Address         NextHop         Interface Metric Preference\n"); -  pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, -		nexthop_addr_str, sizeof(nexthop_addr_str)); +	pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, +		      nexthop_addr_str, sizeof(nexthop_addr_str)); -  vty_out (vty, "%-15s %-15s %-9s %6d %10d\n", -	  addr_str, -	  nexthop_addr_str, -	  nexthop.interface ? nexthop.interface->name : "<ifname?>", -	  nexthop.mrib_route_metric, -	  nexthop.mrib_metric_preference); +	vty_out(vty, "%-15s %-15s %-9s %6d %10d\n", addr_str, nexthop_addr_str, +		nexthop.interface ? nexthop.interface->name : "<ifname?>", +		nexthop.mrib_route_metric, nexthop.mrib_metric_preference); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  static void show_ssmpingd(struct vty *vty)  { -  struct listnode      *node; -  struct ssmpingd_sock *ss; -  time_t                now; +	struct listnode *node; +	struct ssmpingd_sock *ss; +	time_t now; -  vty_out (vty, -            "Source          Socket Address          Port Uptime   Requests\n"); +	vty_out(vty, +		"Source          Socket Address          Port Uptime   Requests\n"); -  if (!qpim_ssmpingd_list) -    return; +	if (!qpim_ssmpingd_list) +		return; -  now = pim_time_monotonic_sec(); +	now = pim_time_monotonic_sec(); -  for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { -    char source_str[INET_ADDRSTRLEN]; -    char ss_uptime[10]; -    struct sockaddr_in bind_addr; -    socklen_t len = sizeof(bind_addr); -    char bind_addr_str[INET_ADDRSTRLEN]; +	for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { +		char source_str[INET_ADDRSTRLEN]; +		char ss_uptime[10]; +		struct sockaddr_in bind_addr; +		socklen_t len = sizeof(bind_addr); +		char bind_addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); +		pim_inet4_dump("<src?>", ss->source_addr, source_str, +			       sizeof(source_str)); -    if (pim_socket_getsockname(ss->sock_fd, (struct sockaddr *) &bind_addr, &len)) { -      vty_out (vty, "%% Failure reading socket name for ssmpingd source %s on fd=%d\n", -	      source_str, ss->sock_fd); -    } +		if (pim_socket_getsockname( +			    ss->sock_fd, (struct sockaddr *)&bind_addr, &len)) { +			vty_out(vty, +				"%% Failure reading socket name for ssmpingd source %s on fd=%d\n", +				source_str, ss->sock_fd); +		} -    pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str, sizeof(bind_addr_str)); -    pim_time_uptime(ss_uptime, sizeof(ss_uptime), now - ss->creation); +		pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str, +			       sizeof(bind_addr_str)); +		pim_time_uptime(ss_uptime, sizeof(ss_uptime), +				now - ss->creation); -    vty_out (vty, "%-15s %6d %-15s %5d %8s %8lld\n", -	    source_str, -	    ss->sock_fd, -	    bind_addr_str, -	    ntohs(bind_addr.sin_port), -	    ss_uptime, -	    (long long)ss->requests); -  } +		vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld\n", source_str, +			ss->sock_fd, bind_addr_str, ntohs(bind_addr.sin_port), +			ss_uptime, (long long)ss->requests); +	}  }  DEFUN (show_ip_ssmpingd, @@ -3740,89 +4217,82 @@ DEFUN (show_ip_ssmpingd,         IP_STR         SHOW_SSMPINGD_STR)  { -  show_ssmpingd(vty); -  return CMD_SUCCESS; +	show_ssmpingd(vty); +	return CMD_SUCCESS;  } -static int -pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const char *plist) +static int pim_rp_cmd_worker(struct vty *vty, const char *rp, const char *group, +			     const char *plist)  { -  int result; +	int result; -  result = pim_rp_new (rp, group, plist); +	result = pim_rp_new(rp, group, plist); -  if (result == PIM_MALLOC_FAIL) -    { -      vty_out (vty, "%% Out of memory\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_MALLOC_FAIL) { +		vty_out(vty, "%% Out of memory\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_GROUP_BAD_ADDRESS) -    { -      vty_out (vty, "%% Bad group address specified: %s\n", group); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_GROUP_BAD_ADDRESS) { +		vty_out(vty, "%% Bad group address specified: %s\n", group); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_RP_BAD_ADDRESS) -    { -      vty_out (vty, "%% Bad RP address specified: %s\n", rp); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_RP_BAD_ADDRESS) { +		vty_out(vty, "%% Bad RP address specified: %s\n", rp); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_RP_NO_PATH) -    { -      vty_out (vty, "%% No Path to RP address specified: %s\n", rp); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_RP_NO_PATH) { +		vty_out(vty, "%% No Path to RP address specified: %s\n", rp); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_GROUP_OVERLAP) -    { -      vty_out (vty, "%% Group range specified cannot overlap\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_GROUP_OVERLAP) { +		vty_out(vty, "%% Group range specified cannot overlap\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_GROUP_PFXLIST_OVERLAP) -    { -      vty_out (vty, -                 "%% This group is already covered by a RP prefix-list\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_GROUP_PFXLIST_OVERLAP) { +		vty_out(vty, +			"%% This group is already covered by a RP prefix-list\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_RP_PFXLIST_IN_USE) -    { -      vty_out (vty, -                 "%% The same prefix-list cannot be applied to multiple RPs\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_RP_PFXLIST_IN_USE) { +		vty_out(vty, +			"%% The same prefix-list cannot be applied to multiple RPs\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -pim_cmd_spt_switchover (enum pim_spt_switchover spt, const char *plist) +static int pim_cmd_spt_switchover(enum pim_spt_switchover spt, +				  const char *plist)  { -  pimg->spt.switchover = spt; +	pimg->spt.switchover = spt; -  switch (pimg->spt.switchover) -    { -    case PIM_SPT_IMMEDIATE: -      if (pimg->spt.plist) -        XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); +	switch (pimg->spt.switchover) { +	case PIM_SPT_IMMEDIATE: +		if (pimg->spt.plist) +			XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); -      pim_upstream_add_lhr_star_pimreg (); -      break; -    case PIM_SPT_INFINITY: -      pim_upstream_remove_lhr_star_pimreg (plist); +		pim_upstream_add_lhr_star_pimreg(); +		break; +	case PIM_SPT_INFINITY: +		pim_upstream_remove_lhr_star_pimreg(plist); -      if (pimg->spt.plist) -        XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); +		if (pimg->spt.plist) +			XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); -      if (plist) -        pimg->spt.plist = XSTRDUP (MTYPE_PIM_SPT_PLIST_NAME, plist); -      break; -    } +		if (plist) +			pimg->spt.plist = +				XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist); +		break; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_spt_switchover_infinity, @@ -3833,7 +4303,7 @@ DEFUN (ip_pim_spt_switchover_infinity,         "SPT-Switchover\n"         "Never switch to SPT Tree\n")  { -  return pim_cmd_spt_switchover (PIM_SPT_INFINITY, NULL); +	return pim_cmd_spt_switchover(PIM_SPT_INFINITY, NULL);  }  DEFUN (ip_pim_spt_switchover_infinity_plist, @@ -3846,7 +4316,7 @@ DEFUN (ip_pim_spt_switchover_infinity_plist,         "Prefix-List to control which groups to switch\n"         "Prefix-List name\n")  { -  return pim_cmd_spt_switchover (PIM_SPT_INFINITY, argv[5]->arg); +	return pim_cmd_spt_switchover(PIM_SPT_INFINITY, argv[5]->arg);  }  DEFUN (no_ip_pim_spt_switchover_infinity, @@ -3858,7 +4328,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity,         "SPT_Switchover\n"         "Never switch to SPT Tree\n")  { -  return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); +	return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL);  }  DEFUN (no_ip_pim_spt_switchover_infinity_plist, @@ -3872,7 +4342,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,         "Prefix-List to control which groups to switch\n"         "Prefix-List name\n")  { -  return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); +	return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL);  }  DEFUN (ip_pim_joinprune_time, @@ -3883,8 +4353,8 @@ DEFUN (ip_pim_joinprune_time,         "Join Prune Send Interval\n"         "Seconds\n")  { -  qpim_t_periodic = atoi(argv[3]->arg); -  return CMD_SUCCESS; +	qpim_t_periodic = atoi(argv[3]->arg); +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_joinprune_time, @@ -3896,8 +4366,8 @@ DEFUN (no_ip_pim_joinprune_time,         "Join Prune Send Interval\n"         "Seconds\n")  { -  qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; -  return CMD_SUCCESS; +	qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_register_suppress, @@ -3908,8 +4378,8 @@ DEFUN (ip_pim_register_suppress,         "Register Suppress Timer\n"         "Seconds\n")  { -  qpim_register_suppress_time = atoi (argv[3]->arg); -  return CMD_SUCCESS; +	qpim_register_suppress_time = atoi(argv[3]->arg); +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_register_suppress, @@ -3921,8 +4391,8 @@ DEFUN (no_ip_pim_register_suppress,         "Register Suppress Timer\n"         "Seconds\n")  { -  qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; -  return CMD_SUCCESS; +	qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_keep_alive, @@ -3933,8 +4403,8 @@ DEFUN (ip_pim_keep_alive,         "Keep alive Timer\n"         "Seconds\n")  { -  qpim_keep_alive_time = atoi (argv[3]->arg); -  return CMD_SUCCESS; +	qpim_keep_alive_time = atoi(argv[3]->arg); +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_keep_alive, @@ -3946,8 +4416,8 @@ DEFUN (no_ip_pim_keep_alive,         "Keep alive Timer\n"         "Seconds\n")  { -  qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; -  return CMD_SUCCESS; +	qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_packets, @@ -3958,8 +4428,8 @@ DEFUN (ip_pim_packets,         "packets to process at one time per fd\n"         "Number of packets\n")  { -  qpim_packet_process = atoi (argv[3]->arg); -  return CMD_SUCCESS; +	qpim_packet_process = atoi(argv[3]->arg); +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_packets, @@ -3971,8 +4441,8 @@ DEFUN (no_ip_pim_packets,         "packets to process at one time per fd\n"         "Number of packets\n")  { -  qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; -  return CMD_SUCCESS; +	qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_v6_secondary, @@ -3982,9 +4452,9 @@ DEFUN (ip_pim_v6_secondary,         "pim multicast routing\n"         "Send v6 secondary addresses\n")  { -  pimg->send_v6_secondary = 1; +	pimg->send_v6_secondary = 1; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_v6_secondary, @@ -3995,9 +4465,9 @@ DEFUN (no_ip_pim_v6_secondary,         "pim multicast routing\n"         "Send v6 secondary addresses\n")  { -  pimg->send_v6_secondary = 0; +	pimg->send_v6_secondary = 0; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_rp, @@ -4009,13 +4479,13 @@ DEFUN (ip_pim_rp,         "ip address of RP\n"         "Group Address range to cover\n")  { -  int idx_ipv4 = 3; - -  if (argc == (idx_ipv4 + 1)) -    return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); -  else -    return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); +	int idx_ipv4 = 3; +	if (argc == (idx_ipv4 + 1)) +		return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, NULL); +	else +		return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, +					 argv[idx_ipv4 + 1]->arg, NULL);  }  DEFUN (ip_pim_rp_prefix_list, @@ -4028,34 +4498,30 @@ DEFUN (ip_pim_rp_prefix_list,         "group prefix-list filter\n"         "Name of a prefix-list\n")  { -  return pim_rp_cmd_worker (vty, argv[3]->arg, NULL, argv[5]->arg); +	return pim_rp_cmd_worker(vty, argv[3]->arg, NULL, argv[5]->arg);  } -static int -pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, -                      const char *plist) +static int pim_no_rp_cmd_worker(struct vty *vty, const char *rp, +				const char *group, const char *plist)  { -  int result = pim_rp_del (rp, group, plist); +	int result = pim_rp_del(rp, group, plist); -  if (result == PIM_GROUP_BAD_ADDRESS) -    { -      vty_out (vty, "%% Bad group address specified: %s\n", group); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_GROUP_BAD_ADDRESS) { +		vty_out(vty, "%% Bad group address specified: %s\n", group); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_RP_BAD_ADDRESS) -    { -      vty_out (vty, "%% Bad RP address specified: %s\n", rp); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_RP_BAD_ADDRESS) { +		vty_out(vty, "%% Bad RP address specified: %s\n", rp); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (result == PIM_RP_NOT_FOUND) -    { -      vty_out (vty, "%% Unable to find specified RP\n"); -      return CMD_WARNING_CONFIG_FAILED; -    } +	if (result == PIM_RP_NOT_FOUND) { +		vty_out(vty, "%% Unable to find specified RP\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_rp, @@ -4068,12 +4534,14 @@ DEFUN (no_ip_pim_rp,         "ip address of RP\n"         "Group Address range to cover\n")  { -  int idx_ipv4 = 4, idx_group = 0; +	int idx_ipv4 = 4, idx_group = 0; -  if (argv_find (argv, argc, "A.B.C.D/M", &idx_group)) -    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_group]->arg, NULL); -  else -    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); +	if (argv_find(argv, argc, "A.B.C.D/M", &idx_group)) +		return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, +					    argv[idx_group]->arg, NULL); +	else +		return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, +					    NULL);  }  DEFUN (no_ip_pim_rp_prefix_list, @@ -4087,30 +4555,28 @@ DEFUN (no_ip_pim_rp_prefix_list,         "group prefix-list filter\n"         "Name of a prefix-list\n")  { -  return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg); +	return pim_no_rp_cmd_worker(vty, argv[4]->arg, NULL, argv[6]->arg);  } -static int -pim_ssm_cmd_worker (struct vty *vty, const char *plist) +static int pim_ssm_cmd_worker(struct vty *vty, const char *plist)  { -  int result = pim_ssm_range_set (VRF_DEFAULT, plist); +	int result = pim_ssm_range_set(VRF_DEFAULT, plist); -  if (result == PIM_SSM_ERR_NONE) -    return CMD_SUCCESS; +	if (result == PIM_SSM_ERR_NONE) +		return CMD_SUCCESS; -  switch (result) -    { -    case PIM_SSM_ERR_NO_VRF: -      vty_out (vty, "%% VRF doesn't exist\n"); -      break; -    case PIM_SSM_ERR_DUP: -      vty_out (vty, "%% duplicate config\n"); -      break; -    default: -      vty_out (vty, "%% ssm range config failed\n"); -    } +	switch (result) { +	case PIM_SSM_ERR_NO_VRF: +		vty_out(vty, "%% VRF doesn't exist\n"); +		break; +	case PIM_SSM_ERR_DUP: +		vty_out(vty, "%% duplicate config\n"); +		break; +	default: +		vty_out(vty, "%% ssm range config failed\n"); +	} -  return CMD_WARNING_CONFIG_FAILED; +	return CMD_WARNING_CONFIG_FAILED;  }  DEFUN (ip_pim_ssm_prefix_list, @@ -4122,7 +4588,7 @@ DEFUN (ip_pim_ssm_prefix_list,         "group range prefix-list filter\n"         "Name of a prefix-list\n")  { -  return pim_ssm_cmd_worker (vty, argv[0]->arg); +	return pim_ssm_cmd_worker(vty, argv[0]->arg);  }  DEFUN (no_ip_pim_ssm_prefix_list, @@ -4134,7 +4600,7 @@ DEFUN (no_ip_pim_ssm_prefix_list,         "Source Specific Multicast\n"         "group range prefix-list filter\n")  { -  return pim_ssm_cmd_worker (vty, NULL); +	return pim_ssm_cmd_worker(vty, NULL);  }  DEFUN (no_ip_pim_ssm_prefix_list_name, @@ -4147,34 +4613,31 @@ DEFUN (no_ip_pim_ssm_prefix_list_name,         "group range prefix-list filter\n"         "Name of a prefix-list\n")  { -  struct pim_ssm *ssm = pimg->ssm_info; +	struct pim_ssm *ssm = pimg->ssm_info; -  if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg)) -    return pim_ssm_cmd_worker (vty, NULL); +	if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg)) +		return pim_ssm_cmd_worker(vty, NULL); -  vty_out (vty, "%% pim ssm prefix-list %s doesn't exist\n", -           argv[0]->arg); +	vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[0]->arg); -  return CMD_WARNING_CONFIG_FAILED; +	return CMD_WARNING_CONFIG_FAILED;  } -static void -ip_pim_ssm_show_group_range(struct vty *vty, u_char uj) +static void ip_pim_ssm_show_group_range(struct vty *vty, u_char uj)  { -  struct pim_ssm *ssm = pimg->ssm_info; -  const char *range_str = ssm->plist_name?ssm->plist_name:PIM_SSM_STANDARD_RANGE; +	struct pim_ssm *ssm = pimg->ssm_info; +	const char *range_str = +		ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE; -  if (uj) -    { -      json_object *json; -      json = json_object_new_object(); -      json_object_string_add(json, "ssmGroups", range_str); -      vty_out (vty, "%s\n", -                 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -      json_object_free(json); -    } -  else -    vty_out (vty, "SSM group range : %s\n", range_str); +	if (uj) { +		json_object *json; +		json = json_object_new_object(); +		json_object_string_add(json, "ssmGroups", range_str); +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} else +		vty_out(vty, "SSM group range : %s\n", range_str);  }  DEFUN (show_ip_pim_ssm_range, @@ -4186,41 +4649,38 @@ DEFUN (show_ip_pim_ssm_range,         "PIM group type\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  ip_pim_ssm_show_group_range(vty, uj); +	u_char uj = use_json(argc, argv); +	ip_pim_ssm_show_group_range(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static void -ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, const char *group) +static void ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, +				       const char *group)  { -  struct in_addr group_addr; -  const char *type_str; -  int result; +	struct in_addr group_addr; +	const char *type_str; +	int result; -  result = inet_pton(AF_INET, group, &group_addr); -  if (result <= 0) -    type_str = "invalid"; -  else -    { -      if (pim_is_group_224_4 (group_addr)) -        type_str = pim_is_grp_ssm (group_addr)?"SSM":"ASM"; -      else -        type_str = "not-multicast"; -    } +	result = inet_pton(AF_INET, group, &group_addr); +	if (result <= 0) +		type_str = "invalid"; +	else { +		if (pim_is_group_224_4(group_addr)) +			type_str = pim_is_grp_ssm(group_addr) ? "SSM" : "ASM"; +		else +			type_str = "not-multicast"; +	} -  if (uj) -    { -      json_object *json; -      json = json_object_new_object(); -      json_object_string_add(json, "groupType", type_str); -      vty_out (vty, "%s\n", -                 json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -      json_object_free(json); -    } -  else -    vty_out (vty, "Group type : %s\n", type_str); +	if (uj) { +		json_object *json; +		json = json_object_new_object(); +		json_object_string_add(json, "groupType", type_str); +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} else +		vty_out(vty, "Group type : %s\n", type_str);  }  DEFUN (show_ip_pim_group_type, @@ -4233,10 +4693,10 @@ DEFUN (show_ip_pim_group_type,         "group address\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg); +	u_char uj = use_json(argc, argv); +	ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN_HIDDEN (ip_multicast_routing, @@ -4245,7 +4705,7 @@ DEFUN_HIDDEN (ip_multicast_routing,                IP_STR                "Enable IP multicast forwarding\n")  { -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN_HIDDEN (no_ip_multicast_routing, @@ -4255,9 +4715,9 @@ DEFUN_HIDDEN (no_ip_multicast_routing,                IP_STR                "Enable IP multicast forwarding\n")  { -  vty_out (vty, -             "Command is Disabled and will be removed in a future version\n"); -  return CMD_SUCCESS; +	vty_out(vty, +		"Command is Disabled and will be removed in a future version\n"); +	return CMD_SUCCESS;  }  DEFUN (ip_ssmpingd, @@ -4267,26 +4727,26 @@ DEFUN (ip_ssmpingd,         CONF_SSMPINGD_STR         "Source address\n")  { -  int idx_ipv4 = 2; -  int result; -  struct in_addr source_addr; -  const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; +	int idx_ipv4 = 2; +	int result; +	struct in_addr source_addr; +	const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; -  result = inet_pton(AF_INET, source_str, &source_addr); -  if (result <= 0) { -    vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", -	    source_str, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = inet_pton(AF_INET, source_str, &source_addr); +	if (result <= 0) { +		vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", +			source_str, errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -  result = pim_ssmpingd_start(source_addr); -  if (result) { -    vty_out (vty, "%% Failure starting ssmpingd for source %s: %d\n", -	    source_str, result); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = pim_ssmpingd_start(source_addr); +	if (result) { +		vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n", +			source_str, result); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ip_ssmpingd, @@ -4297,26 +4757,26 @@ DEFUN (no_ip_ssmpingd,         CONF_SSMPINGD_STR         "Source address\n")  { -  int idx_ipv4 = 3; -  int result; -  struct in_addr source_addr; -  const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; +	int idx_ipv4 = 3; +	int result; +	struct in_addr source_addr; +	const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; -  result = inet_pton(AF_INET, source_str, &source_addr); -  if (result <= 0) { -    vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", -	    source_str, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = inet_pton(AF_INET, source_str, &source_addr); +	if (result <= 0) { +		vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", +			source_str, errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -  result = pim_ssmpingd_stop(source_addr); -  if (result) { -    vty_out (vty, "%% Failure stopping ssmpingd for source %s: %d\n", -	    source_str, result); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = pim_ssmpingd_stop(source_addr); +	if (result) { +		vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n", +			source_str, result); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_ecmp, @@ -4326,9 +4786,9 @@ DEFUN (ip_pim_ecmp,         "pim multicast routing\n"         "Enable PIM ECMP \n")  { -  qpim_ecmp_enable = 1; +	qpim_ecmp_enable = 1; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_ecmp, @@ -4339,9 +4799,9 @@ DEFUN (no_ip_pim_ecmp,         "pim multicast routing\n"         "Disable PIM ECMP \n")  { -  qpim_ecmp_enable = 0; +	qpim_ecmp_enable = 0; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_ecmp_rebalance, @@ -4352,10 +4812,10 @@ DEFUN (ip_pim_ecmp_rebalance,         "Enable PIM ECMP \n"         "Enable PIM ECMP Rebalance\n")  { -  qpim_ecmp_enable = 1; -  qpim_ecmp_rebalance_enable = 1; +	qpim_ecmp_enable = 1; +	qpim_ecmp_rebalance_enable = 1; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_ecmp_rebalance, @@ -4367,48 +4827,41 @@ DEFUN (no_ip_pim_ecmp_rebalance,         "Disable PIM ECMP \n"         "Disable PIM ECMP Rebalance\n")  { -  qpim_ecmp_rebalance_enable = 0; +	qpim_ecmp_rebalance_enable = 0; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -pim_cmd_igmp_start (struct vty *vty, struct interface *ifp) +static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  uint8_t need_startup = 0; +	struct pim_interface *pim_ifp; +	uint8_t need_startup = 0; -  pim_ifp = ifp->info; +	pim_ifp = ifp->info; -  if (!pim_ifp) -    { -      pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); -      if (!pim_ifp) -        { -          vty_out (vty, "Could not enable IGMP on interface %s\n", -	      ifp->name); -          return CMD_WARNING_CONFIG_FAILED; -        } -      need_startup = 1; -    } -  else -    { -      if (!PIM_IF_TEST_IGMP(pim_ifp->options)) -        { -          PIM_IF_DO_IGMP(pim_ifp->options); -          need_startup = 1; -        } -    } +	if (!pim_ifp) { +		pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); +		if (!pim_ifp) { +			vty_out(vty, "Could not enable IGMP on interface %s\n", +				ifp->name); +			return CMD_WARNING_CONFIG_FAILED; +		} +		need_startup = 1; +	} else { +		if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { +			PIM_IF_DO_IGMP(pim_ifp->options); +			need_startup = 1; +		} +	} -  /* 'ip igmp' executed multiple times, with need_startup -    avoid multiple if add all and membership refresh */ -  if (need_startup) -    { -      pim_if_addr_add_all(ifp); -      pim_if_membership_refresh(ifp); -    } +	/* 'ip igmp' executed multiple times, with need_startup +	  avoid multiple if add all and membership refresh */ +	if (need_startup) { +		pim_if_addr_add_all(ifp); +		pim_if_membership_refresh(ifp); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_ip_igmp, @@ -4417,9 +4870,9 @@ DEFUN (interface_ip_igmp,         IP_STR         IFACE_IGMP_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); +	VTY_DECLVAR_CONTEXT(interface, ifp); -  return pim_cmd_igmp_start(vty, ifp); +	return pim_cmd_igmp_start(vty, ifp);  }  DEFUN (interface_no_ip_igmp, @@ -4429,23 +4882,23 @@ DEFUN (interface_no_ip_igmp,         IP_STR         IFACE_IGMP_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) -    return CMD_SUCCESS; +	if (!pim_ifp) +		return CMD_SUCCESS; -  PIM_IF_DONT_IGMP(pim_ifp->options); +	PIM_IF_DONT_IGMP(pim_ifp->options); -  pim_if_membership_clear(ifp); +	pim_if_membership_clear(ifp); -  pim_if_addr_del_all_igmp(ifp); +	pim_if_addr_del_all_igmp(ifp); -  if (!PIM_IF_TEST_PIM(pim_ifp->options)) { -    pim_if_delete(ifp); -  } +	if (!PIM_IF_TEST_PIM(pim_ifp->options)) { +		pim_if_delete(ifp); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_ip_igmp_join, @@ -4457,41 +4910,42 @@ DEFUN (interface_ip_igmp_join,         "Multicast group address\n"         "Source address\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  int idx_ipv4 = 3; -  int idx_ipv4_2 = 4; -  const char *group_str; -  const char *source_str; -  struct in_addr group_addr; -  struct in_addr source_addr; -  int result; - -  /* Group address */ -  group_str = argv[idx_ipv4]->arg; -  result = inet_pton(AF_INET, group_str, &group_addr); -  if (result <= 0) { -    vty_out (vty, "Bad group address %s: errno=%d: %s\n", -	    group_str, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  /* Source address */ -  source_str = argv[idx_ipv4_2]->arg; -  result = inet_pton(AF_INET, source_str, &source_addr); -  if (result <= 0) { -    vty_out (vty, "Bad source address %s: errno=%d: %s\n", -	    source_str, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  result = pim_if_igmp_join_add(ifp, group_addr, source_addr); -  if (result) { -    vty_out (vty, "%% Failure joining IGMP group %s source %s on interface %s: %d\n", -	    group_str, source_str, ifp->name, result); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	int idx_ipv4 = 3; +	int idx_ipv4_2 = 4; +	const char *group_str; +	const char *source_str; +	struct in_addr group_addr; +	struct in_addr source_addr; +	int result; + +	/* Group address */ +	group_str = argv[idx_ipv4]->arg; +	result = inet_pton(AF_INET, group_str, &group_addr); +	if (result <= 0) { +		vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	/* Source address */ +	source_str = argv[idx_ipv4_2]->arg; +	result = inet_pton(AF_INET, source_str, &source_addr); +	if (result <= 0) { +		vty_out(vty, "Bad source address %s: errno=%d: %s\n", +			source_str, errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	result = pim_if_igmp_join_add(ifp, group_addr, source_addr); +	if (result) { +		vty_out(vty, +			"%% Failure joining IGMP group %s source %s on interface %s: %d\n", +			group_str, source_str, ifp->name, result); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_igmp_join, @@ -4504,41 +4958,42 @@ DEFUN (interface_no_ip_igmp_join,         "Multicast group address\n"         "Source address\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  int idx_ipv4 = 4; -  int idx_ipv4_2 = 5; -  const char *group_str; -  const char *source_str; -  struct in_addr group_addr; -  struct in_addr source_addr; -  int result; - -  /* Group address */ -  group_str = argv[idx_ipv4]->arg; -  result = inet_pton(AF_INET, group_str, &group_addr); -  if (result <= 0) { -    vty_out (vty, "Bad group address %s: errno=%d: %s\n", -	    group_str, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  /* Source address */ -  source_str = argv[idx_ipv4_2]->arg; -  result = inet_pton(AF_INET, source_str, &source_addr); -  if (result <= 0) { -    vty_out (vty, "Bad source address %s: errno=%d: %s\n", -	    source_str, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  result = pim_if_igmp_join_del(ifp, group_addr, source_addr); -  if (result) { -    vty_out (vty, "%% Failure leaving IGMP group %s source %s on interface %s: %d\n", -	    group_str, source_str, ifp->name, result); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	int idx_ipv4 = 4; +	int idx_ipv4_2 = 5; +	const char *group_str; +	const char *source_str; +	struct in_addr group_addr; +	struct in_addr source_addr; +	int result; + +	/* Group address */ +	group_str = argv[idx_ipv4]->arg; +	result = inet_pton(AF_INET, group_str, &group_addr); +	if (result <= 0) { +		vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	/* Source address */ +	source_str = argv[idx_ipv4_2]->arg; +	result = inet_pton(AF_INET, source_str, &source_addr); +	if (result <= 0) { +		vty_out(vty, "Bad source address %s: errno=%d: %s\n", +			source_str, errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	result = pim_if_igmp_join_del(ifp, group_addr, source_addr); +	if (result) { +		vty_out(vty, +			"%% Failure leaving IGMP group %s source %s on interface %s: %d\n", +			group_str, source_str, ifp->name, result); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	return CMD_SUCCESS;  }  /* @@ -4548,125 +5003,127 @@ DEFUN (interface_no_ip_igmp_join,   */  static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)  { -  struct interface *ifp; -  struct pim_interface *pim_ifp; +	struct interface *ifp; +	struct pim_interface *pim_ifp; -  zassert(igmp); +	zassert(igmp); -  /* other querier present? */ +	/* other querier present? */ -  if (igmp->t_other_querier_timer) -    return; +	if (igmp->t_other_querier_timer) +		return; -  /* this is the querier */ +	/* this is the querier */ -  zassert(igmp->interface); -  zassert(igmp->interface->info); +	zassert(igmp->interface); +	zassert(igmp->interface->info); -  ifp = igmp->interface; -  pim_ifp = ifp->info; +	ifp = igmp->interface; +	pim_ifp = ifp->info; -  if (PIM_DEBUG_IGMP_TRACE) { -    char ifaddr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -    zlog_debug("%s: Querier %s on %s reconfig query_interval=%d", -	       __PRETTY_FUNCTION__, -	       ifaddr_str, -	       ifp->name, -	       pim_ifp->igmp_default_query_interval); -  } +	if (PIM_DEBUG_IGMP_TRACE) { +		char ifaddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +			       sizeof(ifaddr_str)); +		zlog_debug("%s: Querier %s on %s reconfig query_interval=%d", +			   __PRETTY_FUNCTION__, ifaddr_str, ifp->name, +			   pim_ifp->igmp_default_query_interval); +	} -  /* -    igmp_startup_mode_on() will reset QQI: +	/* +	  igmp_startup_mode_on() will reset QQI: -    igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; -  */ -  igmp_startup_mode_on(igmp); +	  igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; +	*/ +	igmp_startup_mode_on(igmp);  }  static void igmp_sock_query_reschedule(struct igmp_sock *igmp)  { -  if (igmp->t_igmp_query_timer) { -    /* other querier present */ -    zassert(igmp->t_igmp_query_timer); -    zassert(!igmp->t_other_querier_timer); +	if (igmp->t_igmp_query_timer) { +		/* other querier present */ +		zassert(igmp->t_igmp_query_timer); +		zassert(!igmp->t_other_querier_timer); -    pim_igmp_general_query_off(igmp); -    pim_igmp_general_query_on(igmp); +		pim_igmp_general_query_off(igmp); +		pim_igmp_general_query_on(igmp); -    zassert(igmp->t_igmp_query_timer); -    zassert(!igmp->t_other_querier_timer); -  } -  else { -    /* this is the querier */ +		zassert(igmp->t_igmp_query_timer); +		zassert(!igmp->t_other_querier_timer); +	} else { +		/* this is the querier */ -    zassert(!igmp->t_igmp_query_timer); -    zassert(igmp->t_other_querier_timer); +		zassert(!igmp->t_igmp_query_timer); +		zassert(igmp->t_other_querier_timer); -    pim_igmp_other_querier_timer_off(igmp); -    pim_igmp_other_querier_timer_on(igmp); +		pim_igmp_other_querier_timer_off(igmp); +		pim_igmp_other_querier_timer_on(igmp); -    zassert(!igmp->t_igmp_query_timer); -    zassert(igmp->t_other_querier_timer); -  } +		zassert(!igmp->t_igmp_query_timer); +		zassert(igmp->t_other_querier_timer); +	}  }  static void change_query_interval(struct pim_interface *pim_ifp,  				  int query_interval)  { -  struct listnode  *sock_node; -  struct igmp_sock *igmp; +	struct listnode *sock_node; +	struct igmp_sock *igmp; -  pim_ifp->igmp_default_query_interval = query_interval; +	pim_ifp->igmp_default_query_interval = query_interval; -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -    igmp_sock_query_interval_reconfig(igmp); -    igmp_sock_query_reschedule(igmp); -  } +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { +		igmp_sock_query_interval_reconfig(igmp); +		igmp_sock_query_reschedule(igmp); +	}  }  static void change_query_max_response_time(struct pim_interface *pim_ifp,  					   int query_max_response_time_dsec)  { -  struct listnode  *sock_node; -  struct igmp_sock *igmp; - -  pim_ifp->igmp_query_max_response_time_dsec = query_max_response_time_dsec; - -  /* -    Below we modify socket/group/source timers in order to quickly -    reflect the change. Otherwise, those timers would eventually catch -    up. -   */ - -  /* scan all sockets */ -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { -    struct listnode   *grp_node; -    struct igmp_group *grp; - -    /* reschedule socket general query */ -    igmp_sock_query_reschedule(igmp); - -    /* scan socket groups */ -    for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, grp)) { -      struct listnode    *src_node; -      struct igmp_source *src; - -      /* reset group timers for groups in EXCLUDE mode */ -      if (grp->group_filtermode_isexcl) { -	igmp_group_reset_gmi(grp); -      } - -      /* scan group sources */ -      for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) { - -	/* reset source timers for sources with running timers */ -	if (src->t_source_timer) { -	  igmp_source_reset_gmi(igmp, grp, src); +	struct listnode *sock_node; +	struct igmp_sock *igmp; + +	pim_ifp->igmp_query_max_response_time_dsec = +		query_max_response_time_dsec; + +	/* +	  Below we modify socket/group/source timers in order to quickly +	  reflect the change. Otherwise, those timers would eventually catch +	  up. +	 */ + +	/* scan all sockets */ +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { +		struct listnode *grp_node; +		struct igmp_group *grp; + +		/* reschedule socket general query */ +		igmp_sock_query_reschedule(igmp); + +		/* scan socket groups */ +		for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, +					  grp)) { +			struct listnode *src_node; +			struct igmp_source *src; + +			/* reset group timers for groups in EXCLUDE mode */ +			if (grp->group_filtermode_isexcl) { +				igmp_group_reset_gmi(grp); +			} + +			/* scan group sources */ +			for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, +						  src_node, src)) { + +				/* reset source timers for sources with running +				 * timers */ +				if (src->t_source_timer) { +					igmp_source_reset_gmi(igmp, grp, src); +				} +			} +		}  	} -      } -    } -  }  }  #define IGMP_QUERY_INTERVAL_MIN (1) @@ -4680,49 +5137,50 @@ DEFUN (interface_ip_igmp_query_interval,         IFACE_IGMP_QUERY_INTERVAL_STR         "Query interval in seconds\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; -  int query_interval; -  int query_interval_dsec; -  int ret; - -  if (!pim_ifp) { -    ret = pim_cmd_igmp_start(vty, ifp); -    if (ret != CMD_SUCCESS) -      return ret; -    pim_ifp = ifp->info; -  } - -  query_interval = atoi(argv[3]->arg); -  query_interval_dsec = 10 * query_interval; - -  /* -    It seems we don't need to check bounds since command.c does it -    already, but we verify them anyway for extra safety. -  */ -  if (query_interval < IGMP_QUERY_INTERVAL_MIN) { -    vty_out (vty, "General query interval %d lower than minimum %d\n", -	    query_interval, -	    IGMP_QUERY_INTERVAL_MIN); -    return CMD_WARNING_CONFIG_FAILED; -  } -  if (query_interval > IGMP_QUERY_INTERVAL_MAX) { -    vty_out (vty, "General query interval %d higher than maximum %d\n", -	    query_interval, -	    IGMP_QUERY_INTERVAL_MAX); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { -    vty_out (vty, -	    "Can't set general query interval %d dsec <= query max response time %d dsec.\n", -	    query_interval_dsec,pim_ifp->igmp_query_max_response_time_dsec); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  change_query_interval(pim_ifp, query_interval); - -  return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; +	int query_interval; +	int query_interval_dsec; +	int ret; + +	if (!pim_ifp) { +		ret = pim_cmd_igmp_start(vty, ifp); +		if (ret != CMD_SUCCESS) +			return ret; +		pim_ifp = ifp->info; +	} + +	query_interval = atoi(argv[3]->arg); +	query_interval_dsec = 10 * query_interval; + +	/* +	  It seems we don't need to check bounds since command.c does it +	  already, but we verify them anyway for extra safety. +	*/ +	if (query_interval < IGMP_QUERY_INTERVAL_MIN) { +		vty_out(vty, +			"General query interval %d lower than minimum %d\n", +			query_interval, IGMP_QUERY_INTERVAL_MIN); +		return CMD_WARNING_CONFIG_FAILED; +	} +	if (query_interval > IGMP_QUERY_INTERVAL_MAX) { +		vty_out(vty, +			"General query interval %d higher than maximum %d\n", +			query_interval, IGMP_QUERY_INTERVAL_MAX); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { +		vty_out(vty, +			"Can't set general query interval %d dsec <= query max response time %d dsec.\n", +			query_interval_dsec, +			pim_ifp->igmp_query_max_response_time_dsec); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	change_query_interval(pim_ifp, query_interval); + +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_igmp_query_interval, @@ -4733,26 +5191,27 @@ DEFUN (interface_no_ip_igmp_query_interval,         IFACE_IGMP_STR         IFACE_IGMP_QUERY_INTERVAL_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; -  int default_query_interval_dsec; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; +	int default_query_interval_dsec; -  if (!pim_ifp) -    return CMD_SUCCESS; +	if (!pim_ifp) +		return CMD_SUCCESS; -  default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10; +	default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10; -  if (default_query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { -    vty_out (vty, -	    "Can't set default general query interval %d dsec <= query max response time %d dsec.\n", -	    default_query_interval_dsec, -	    pim_ifp->igmp_query_max_response_time_dsec); -    return CMD_WARNING_CONFIG_FAILED; -  } +	if (default_query_interval_dsec +	    <= pim_ifp->igmp_query_max_response_time_dsec) { +		vty_out(vty, +			"Can't set default general query interval %d dsec <= query max response time %d dsec.\n", +			default_query_interval_dsec, +			pim_ifp->igmp_query_max_response_time_dsec); +		return CMD_WARNING_CONFIG_FAILED; +	} -  change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL); +	change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_ip_igmp_version, @@ -4763,37 +5222,36 @@ DEFUN (interface_ip_igmp_version,         "IGMP version\n"         "IGMP version number\n")  { -  VTY_DECLVAR_CONTEXT(interface,ifp); -  struct pim_interface *pim_ifp = ifp->info; -  int igmp_version, old_version = 0; -  int ret; - -  if (!pim_ifp) -    { -      ret = pim_cmd_igmp_start(vty, ifp); -      if (ret != CMD_SUCCESS) -        return ret; -      pim_ifp = ifp->info; -    } - -  igmp_version = atoi(argv[3]->arg); -  old_version = pim_ifp->igmp_version; -  pim_ifp->igmp_version = igmp_version; - -  //Check if IGMP is Enabled otherwise, enable on interface -  if (!PIM_IF_TEST_IGMP (pim_ifp->options)) -    { -      PIM_IF_DO_IGMP(pim_ifp->options); -      pim_if_addr_add_all(ifp); -      pim_if_membership_refresh(ifp); -      old_version = igmp_version;   //avoid refreshing membership again. -    } -  /* Current and new version is different refresh existing -     membership. Going from 3 -> 2 or 2 -> 3. */ -  if (old_version != igmp_version) -    pim_if_membership_refresh(ifp); - -  return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; +	int igmp_version, old_version = 0; +	int ret; + +	if (!pim_ifp) { +		ret = pim_cmd_igmp_start(vty, ifp); +		if (ret != CMD_SUCCESS) +			return ret; +		pim_ifp = ifp->info; +	} + +	igmp_version = atoi(argv[3]->arg); +	old_version = pim_ifp->igmp_version; +	pim_ifp->igmp_version = igmp_version; + +	// Check if IGMP is Enabled otherwise, enable on interface +	if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { +		PIM_IF_DO_IGMP(pim_ifp->options); +		pim_if_addr_add_all(ifp); +		pim_if_membership_refresh(ifp); +		old_version = igmp_version; // avoid refreshing membership +					    // again. +	} +	/* Current and new version is different refresh existing +	   membership. Going from 3 -> 2 or 2 -> 3. */ +	if (old_version != igmp_version) +		pim_if_membership_refresh(ifp); + +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_igmp_version, @@ -4805,15 +5263,15 @@ DEFUN (interface_no_ip_igmp_version,         "IGMP version\n"         "IGMP version number\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) -    return CMD_SUCCESS; +	if (!pim_ifp) +		return CMD_SUCCESS; -  pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; +	pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) @@ -4827,30 +5285,32 @@ DEFUN (interface_ip_igmp_query_max_response_time,         IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR         "Query response value in deci-seconds\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; -  int query_max_response_time; -  int ret; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; +	int query_max_response_time; +	int ret; -  if (!pim_ifp) { -    ret = pim_cmd_igmp_start(vty, ifp); -    if (ret != CMD_SUCCESS) -      return ret; -    pim_ifp = ifp->info; -  } +	if (!pim_ifp) { +		ret = pim_cmd_igmp_start(vty, ifp); +		if (ret != CMD_SUCCESS) +			return ret; +		pim_ifp = ifp->info; +	} -  query_max_response_time = atoi(argv[3]->arg); +	query_max_response_time = atoi(argv[3]->arg); -  if (query_max_response_time >= pim_ifp->igmp_default_query_interval * 10) { -    vty_out (vty, -	    "Can't set query max response time %d sec >= general query interval %d sec\n", -	    query_max_response_time,pim_ifp->igmp_default_query_interval); -    return CMD_WARNING_CONFIG_FAILED; -  } +	if (query_max_response_time +	    >= pim_ifp->igmp_default_query_interval * 10) { +		vty_out(vty, +			"Can't set query max response time %d sec >= general query interval %d sec\n", +			query_max_response_time, +			pim_ifp->igmp_default_query_interval); +		return CMD_WARNING_CONFIG_FAILED; +	} -  change_query_max_response_time(pim_ifp, query_max_response_time); +	change_query_max_response_time(pim_ifp, query_max_response_time); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_igmp_query_max_response_time, @@ -4862,15 +5322,16 @@ DEFUN (interface_no_ip_igmp_query_max_response_time,         IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR         "Time for response in deci-seconds\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) -    return CMD_SUCCESS; +	if (!pim_ifp) +		return CMD_SUCCESS; -  change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); +	change_query_max_response_time(pim_ifp, +				       IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) @@ -4884,33 +5345,34 @@ DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,  	      IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR  	      "Query response value in deciseconds\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; -  int query_max_response_time_dsec; -  int default_query_interval_dsec; -  int ret; - -  if (!pim_ifp) { -    ret = pim_cmd_igmp_start(vty, ifp); -    if (ret != CMD_SUCCESS) -      return ret; -    pim_ifp = ifp->info; -  } +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; +	int query_max_response_time_dsec; +	int default_query_interval_dsec; +	int ret; + +	if (!pim_ifp) { +		ret = pim_cmd_igmp_start(vty, ifp); +		if (ret != CMD_SUCCESS) +			return ret; +		pim_ifp = ifp->info; +	} -  query_max_response_time_dsec = atoi(argv[4]->arg); +	query_max_response_time_dsec = atoi(argv[4]->arg); -  default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; +	default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; -  if (query_max_response_time_dsec >= default_query_interval_dsec) { -    vty_out (vty, -	    "Can't set query max response time %d dsec >= general query interval %d dsec\n", -	    query_max_response_time_dsec,default_query_interval_dsec); -    return CMD_WARNING_CONFIG_FAILED; -  } +	if (query_max_response_time_dsec >= default_query_interval_dsec) { +		vty_out(vty, +			"Can't set query max response time %d dsec >= general query interval %d dsec\n", +			query_max_response_time_dsec, +			default_query_interval_dsec); +		return CMD_WARNING_CONFIG_FAILED; +	} -  change_query_max_response_time(pim_ifp, query_max_response_time_dsec); +	change_query_max_response_time(pim_ifp, query_max_response_time_dsec); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec, @@ -4921,15 +5383,16 @@ DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,  	      IFACE_IGMP_STR  	      IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) -    return CMD_SUCCESS; +	if (!pim_ifp) +		return CMD_SUCCESS; -  change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); +	change_query_max_response_time(pim_ifp, +				       IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_ip_pim_drprio, @@ -4940,26 +5403,26 @@ DEFUN (interface_ip_pim_drprio,         "Set the Designated Router Election Priority\n"         "Value of the new DR Priority\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  int idx_number = 3; -  struct pim_interface *pim_ifp = ifp->info; -  uint32_t old_dr_prio; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	int idx_number = 3; +	struct pim_interface *pim_ifp = ifp->info; +	uint32_t old_dr_prio; -  if (!pim_ifp) { -    vty_out (vty, "Please enable PIM on interface, first\n"); -    return CMD_WARNING_CONFIG_FAILED; -  } +	if (!pim_ifp) { +		vty_out(vty, "Please enable PIM on interface, first\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  old_dr_prio = pim_ifp->pim_dr_priority; +	old_dr_prio = pim_ifp->pim_dr_priority; -  pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10); +	pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10); -  if (old_dr_prio != pim_ifp->pim_dr_priority) { -    if (pim_if_dr_election(ifp)) -      pim_hello_restart_now(ifp); -  } +	if (old_dr_prio != pim_ifp->pim_dr_priority) { +		if (pim_if_dr_election(ifp)) +			pim_hello_restart_now(ifp); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_pim_drprio, @@ -4971,41 +5434,39 @@ DEFUN (interface_no_ip_pim_drprio,         "Revert the Designated Router Priority to default\n"         "Old Value of the Priority\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) { -    vty_out (vty, "Pim not enabled on this interface\n"); -    return CMD_WARNING_CONFIG_FAILED; -  } +	if (!pim_ifp) { +		vty_out(vty, "Pim not enabled on this interface\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { -    pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; -    if (pim_if_dr_election(ifp)) -      pim_hello_restart_now(ifp); -  } +	if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { +		pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; +		if (pim_if_dr_election(ifp)) +			pim_hello_restart_now(ifp); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -pim_cmd_interface_add (struct interface *ifp) +static int pim_cmd_interface_add(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) { -    pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */); -    if (!pim_ifp) { -      return 0; -    } -  } -  else { -    PIM_IF_DO_PIM(pim_ifp->options); -  } +	if (!pim_ifp) { +		pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */); +		if (!pim_ifp) { +			return 0; +		} +	} else { +		PIM_IF_DO_PIM(pim_ifp->options); +	} -  pim_if_addr_add_all(ifp); -  pim_if_membership_refresh(ifp); -  return 1; +	pim_if_addr_add_all(ifp); +	pim_if_membership_refresh(ifp); +	return 1;  }  DEFUN_HIDDEN (interface_ip_pim_ssm, @@ -5015,16 +5476,17 @@ DEFUN_HIDDEN (interface_ip_pim_ssm,         PIM_STR         IFACE_PIM_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); +	VTY_DECLVAR_CONTEXT(interface, ifp); -  if (!pim_cmd_interface_add(ifp)) { -    vty_out (vty, "Could not enable PIM SM on interface\n"); -    return CMD_WARNING_CONFIG_FAILED; -  } +	if (!pim_cmd_interface_add(ifp)) { +		vty_out(vty, "Could not enable PIM SM on interface\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  vty_out(vty, "WARN: Enabled PIM SM on interface; configure PIM SSM " -                 "range if needed\n"); -  return CMD_SUCCESS; +	vty_out(vty, +		"WARN: Enabled PIM SM on interface; configure PIM SSM " +		"range if needed\n"); +	return CMD_SUCCESS;  }  DEFUN (interface_ip_pim_sm, @@ -5034,41 +5496,40 @@ DEFUN (interface_ip_pim_sm,         PIM_STR         IFACE_PIM_SM_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  if (!pim_cmd_interface_add(ifp)) { -    vty_out (vty, "Could not enable PIM SM on interface\n"); -    return CMD_WARNING_CONFIG_FAILED; -  } +	VTY_DECLVAR_CONTEXT(interface, ifp); +	if (!pim_cmd_interface_add(ifp)) { +		vty_out(vty, "Could not enable PIM SM on interface\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  pim_if_create_pimreg(); +	pim_if_create_pimreg(); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static int -pim_cmd_interface_delete (struct interface *ifp) +static int pim_cmd_interface_delete(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) -    return 1; +	if (!pim_ifp) +		return 1; -  PIM_IF_DONT_PIM(pim_ifp->options); +	PIM_IF_DONT_PIM(pim_ifp->options); -  pim_if_membership_clear(ifp); +	pim_if_membership_clear(ifp); -  /* -    pim_sock_delete() removes all neighbors from -    pim_ifp->pim_neighbor_list. -   */ -  pim_sock_delete(ifp, "pim unconfigured on interface"); +	/* +	  pim_sock_delete() removes all neighbors from +	  pim_ifp->pim_neighbor_list. +	 */ +	pim_sock_delete(ifp, "pim unconfigured on interface"); -  if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { -    pim_if_addr_del_all(ifp); -    pim_if_delete(ifp); -  } +	if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { +		pim_if_addr_del_all(ifp); +		pim_if_delete(ifp); +	} -  return 1; +	return 1;  }  DEFUN_HIDDEN (interface_no_ip_pim_ssm, @@ -5079,13 +5540,13 @@ DEFUN_HIDDEN (interface_no_ip_pim_ssm,         PIM_STR         IFACE_PIM_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  if (!pim_cmd_interface_delete(ifp)) { -    vty_out (vty, "Unable to delete interface information\n"); -    return CMD_WARNING_CONFIG_FAILED; -  } +	VTY_DECLVAR_CONTEXT(interface, ifp); +	if (!pim_cmd_interface_delete(ifp)) { +		vty_out(vty, "Unable to delete interface information\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_pim_sm, @@ -5096,13 +5557,13 @@ DEFUN (interface_no_ip_pim_sm,         PIM_STR         IFACE_PIM_SM_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  if (!pim_cmd_interface_delete(ifp)) { -    vty_out (vty, "Unable to delete interface information\n"); -    return CMD_WARNING_CONFIG_FAILED; -  } +	VTY_DECLVAR_CONTEXT(interface, ifp); +	if (!pim_cmd_interface_delete(ifp)) { +		vty_out(vty, "Unable to delete interface information\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (interface_ip_mroute, @@ -5113,40 +5574,39 @@ DEFUN (interface_ip_mroute,         "Outgoing interface name\n"         "Group address\n")  { -  VTY_DECLVAR_CONTEXT(interface, iif); -  int idx_interface = 2; -  int idx_ipv4 = 3; -   struct interface *oif; -   const char       *oifname; -   const char       *grp_str; -   struct in_addr    grp_addr; -   struct in_addr    src_addr; -   int               result; - -   oifname = argv[idx_interface]->arg; -   oif = if_lookup_by_name(oifname, VRF_DEFAULT); -   if (!oif) { -     vty_out (vty, "No such interface name %s\n", -        oifname); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   grp_str = argv[idx_ipv4]->arg; -   result = inet_pton(AF_INET, grp_str, &grp_addr); -   if (result <= 0) { -     vty_out (vty, "Bad group address %s: errno=%d: %s\n", -        grp_str, errno, safe_strerror(errno)); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   src_addr.s_addr = INADDR_ANY; - -   if (pim_static_add(iif, oif, grp_addr, src_addr)) { -      vty_out (vty, "Failed to add route\n"); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, iif); +	int idx_interface = 2; +	int idx_ipv4 = 3; +	struct interface *oif; +	const char *oifname; +	const char *grp_str; +	struct in_addr grp_addr; +	struct in_addr src_addr; +	int result; + +	oifname = argv[idx_interface]->arg; +	oif = if_lookup_by_name(oifname, VRF_DEFAULT); +	if (!oif) { +		vty_out(vty, "No such interface name %s\n", oifname); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	grp_str = argv[idx_ipv4]->arg; +	result = inet_pton(AF_INET, grp_str, &grp_addr); +	if (result <= 0) { +		vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	src_addr.s_addr = INADDR_ANY; + +	if (pim_static_add(iif, oif, grp_addr, src_addr)) { +		vty_out(vty, "Failed to add route\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	return CMD_SUCCESS;  }  DEFUN (interface_ip_mroute_source, @@ -5158,48 +5618,47 @@ DEFUN (interface_ip_mroute_source,         "Group address\n"         "Source address\n")  { -  VTY_DECLVAR_CONTEXT(interface, iif); -  int idx_interface = 2; -  int idx_ipv4 = 3; -  int idx_ipv4_2 = 4; -   struct interface *oif; -   const char       *oifname; -   const char       *grp_str; -   struct in_addr    grp_addr; -   const char       *src_str; -   struct in_addr    src_addr; -   int               result; - -   oifname = argv[idx_interface]->arg; -   oif = if_lookup_by_name(oifname, VRF_DEFAULT); -   if (!oif) { -     vty_out (vty, "No such interface name %s\n", -        oifname); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   grp_str = argv[idx_ipv4]->arg; -   result = inet_pton(AF_INET, grp_str, &grp_addr); -   if (result <= 0) { -     vty_out (vty, "Bad group address %s: errno=%d: %s\n", -        grp_str, errno, safe_strerror(errno)); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   src_str = argv[idx_ipv4_2]->arg; -   result = inet_pton(AF_INET, src_str, &src_addr); -   if (result <= 0) { -     vty_out (vty, "Bad source address %s: errno=%d: %s\n", -        src_str, errno, safe_strerror(errno)); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   if (pim_static_add(iif, oif, grp_addr, src_addr)) { -      vty_out (vty, "Failed to add route\n"); -      return CMD_WARNING_CONFIG_FAILED; -   } - -   return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, iif); +	int idx_interface = 2; +	int idx_ipv4 = 3; +	int idx_ipv4_2 = 4; +	struct interface *oif; +	const char *oifname; +	const char *grp_str; +	struct in_addr grp_addr; +	const char *src_str; +	struct in_addr src_addr; +	int result; + +	oifname = argv[idx_interface]->arg; +	oif = if_lookup_by_name(oifname, VRF_DEFAULT); +	if (!oif) { +		vty_out(vty, "No such interface name %s\n", oifname); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	grp_str = argv[idx_ipv4]->arg; +	result = inet_pton(AF_INET, grp_str, &grp_addr); +	if (result <= 0) { +		vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	src_str = argv[idx_ipv4_2]->arg; +	result = inet_pton(AF_INET, src_str, &src_addr); +	if (result <= 0) { +		vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	if (pim_static_add(iif, oif, grp_addr, src_addr)) { +		vty_out(vty, "Failed to add route\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_mroute, @@ -5211,40 +5670,39 @@ DEFUN (interface_no_ip_mroute,         "Outgoing interface name\n"         "Group Address\n")  { -  VTY_DECLVAR_CONTEXT(interface, iif); -  int idx_interface = 3; -  int idx_ipv4 = 4; -   struct interface *oif; -   const char       *oifname; -   const char       *grp_str; -   struct in_addr    grp_addr; -   struct in_addr    src_addr; -   int               result; - -   oifname = argv[idx_interface]->arg; -   oif = if_lookup_by_name(oifname, VRF_DEFAULT); -   if (!oif) { -     vty_out (vty, "No such interface name %s\n", -        oifname); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   grp_str = argv[idx_ipv4]->arg; -   result = inet_pton(AF_INET, grp_str, &grp_addr); -   if (result <= 0) { -     vty_out (vty, "Bad group address %s: errno=%d: %s\n", -        grp_str, errno, safe_strerror(errno)); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   src_addr.s_addr = INADDR_ANY; - -   if (pim_static_del(iif, oif, grp_addr, src_addr)) { -      vty_out (vty, "Failed to remove route\n"); -      return CMD_WARNING_CONFIG_FAILED; -   } - -   return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, iif); +	int idx_interface = 3; +	int idx_ipv4 = 4; +	struct interface *oif; +	const char *oifname; +	const char *grp_str; +	struct in_addr grp_addr; +	struct in_addr src_addr; +	int result; + +	oifname = argv[idx_interface]->arg; +	oif = if_lookup_by_name(oifname, VRF_DEFAULT); +	if (!oif) { +		vty_out(vty, "No such interface name %s\n", oifname); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	grp_str = argv[idx_ipv4]->arg; +	result = inet_pton(AF_INET, grp_str, &grp_addr); +	if (result <= 0) { +		vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	src_addr.s_addr = INADDR_ANY; + +	if (pim_static_del(iif, oif, grp_addr, src_addr)) { +		vty_out(vty, "Failed to remove route\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	return CMD_SUCCESS;  }  DEFUN (interface_no_ip_mroute_source, @@ -5257,48 +5715,47 @@ DEFUN (interface_no_ip_mroute_source,         "Group Address\n"         "Source Address\n")  { -  VTY_DECLVAR_CONTEXT(interface, iif); -  int idx_interface = 3; -  int idx_ipv4 = 4; -  int idx_ipv4_2 = 5; -   struct interface *oif; -   const char       *oifname; -   const char       *grp_str; -   struct in_addr    grp_addr; -   const char       *src_str; -   struct in_addr    src_addr; -   int               result; - -   oifname = argv[idx_interface]->arg; -   oif = if_lookup_by_name(oifname, VRF_DEFAULT); -   if (!oif) { -     vty_out (vty, "No such interface name %s\n", -        oifname); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   grp_str = argv[idx_ipv4]->arg; -   result = inet_pton(AF_INET, grp_str, &grp_addr); -   if (result <= 0) { -     vty_out (vty, "Bad group address %s: errno=%d: %s\n", -        grp_str, errno, safe_strerror(errno)); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   src_str = argv[idx_ipv4_2]->arg; -   result = inet_pton(AF_INET, src_str, &src_addr); -   if (result <= 0) { -     vty_out (vty, "Bad source address %s: errno=%d: %s\n", -        src_str, errno, safe_strerror(errno)); -     return CMD_WARNING_CONFIG_FAILED; -   } - -   if (pim_static_del(iif, oif, grp_addr, src_addr)) { -      vty_out (vty, "Failed to remove route\n"); -      return CMD_WARNING_CONFIG_FAILED; -   } - -   return CMD_SUCCESS; +	VTY_DECLVAR_CONTEXT(interface, iif); +	int idx_interface = 3; +	int idx_ipv4 = 4; +	int idx_ipv4_2 = 5; +	struct interface *oif; +	const char *oifname; +	const char *grp_str; +	struct in_addr grp_addr; +	const char *src_str; +	struct in_addr src_addr; +	int result; + +	oifname = argv[idx_interface]->arg; +	oif = if_lookup_by_name(oifname, VRF_DEFAULT); +	if (!oif) { +		vty_out(vty, "No such interface name %s\n", oifname); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	grp_str = argv[idx_ipv4]->arg; +	result = inet_pton(AF_INET, grp_str, &grp_addr); +	if (result <= 0) { +		vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	src_str = argv[idx_ipv4_2]->arg; +	result = inet_pton(AF_INET, src_str, &src_addr); +	if (result <= 0) { +		vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	if (pim_static_del(iif, oif, grp_addr, src_addr)) { +		vty_out(vty, "Failed to remove route\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	return CMD_SUCCESS;  }  DEFUN (interface_ip_pim_hello, @@ -5310,31 +5767,29 @@ DEFUN (interface_ip_pim_hello,         IFACE_PIM_HELLO_TIME_STR         IFACE_PIM_HELLO_HOLD_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  int idx_time = 3; -  int idx_hold = 4; -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	int idx_time = 3; +	int idx_hold = 4; +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) -    { -      if (!pim_cmd_interface_add(ifp)) -        { -          vty_out (vty, "Could not enable PIM SM on interface\n"); -          return CMD_WARNING_CONFIG_FAILED; -        } -    } +	if (!pim_ifp) { +		if (!pim_cmd_interface_add(ifp)) { +			vty_out(vty, "Could not enable PIM SM on interface\n"); +			return CMD_WARNING_CONFIG_FAILED; +		} +	} -  pim_ifp = ifp->info; -  pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); +	pim_ifp = ifp->info; +	pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); -  if (argc == idx_hold + 1) -    pim_ifp->pim_default_holdtime = strtol(argv[idx_hold]->arg, NULL, 10); +	if (argc == idx_hold + 1) +		pim_ifp->pim_default_holdtime = +			strtol(argv[idx_hold]->arg, NULL, 10); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -  DEFUN (interface_no_ip_pim_hello,         interface_no_ip_pim_hello_cmd,         "no ip pim hello [(1-180) (1-180)]", @@ -5345,18 +5800,18 @@ DEFUN (interface_no_ip_pim_hello,         IFACE_PIM_HELLO_TIME_STR         IFACE_PIM_HELLO_HOLD_STR)  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) { -    vty_out (vty, "Pim not enabled on this interface\n"); -    return CMD_WARNING_CONFIG_FAILED; -  } +	if (!pim_ifp) { +		vty_out(vty, "Pim not enabled on this interface\n"); +		return CMD_WARNING_CONFIG_FAILED; +	} -  pim_ifp->pim_hello_period     = PIM_DEFAULT_HELLO_PERIOD; -  pim_ifp->pim_default_holdtime = -1; +	pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; +	pim_ifp->pim_default_holdtime = -1; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (debug_igmp, @@ -5365,10 +5820,10 @@ DEFUN (debug_igmp,         DEBUG_STR         DEBUG_IGMP_STR)  { -  PIM_DO_DEBUG_IGMP_EVENTS; -  PIM_DO_DEBUG_IGMP_PACKETS; -  PIM_DO_DEBUG_IGMP_TRACE; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_IGMP_EVENTS; +	PIM_DO_DEBUG_IGMP_PACKETS; +	PIM_DO_DEBUG_IGMP_TRACE; +	return CMD_SUCCESS;  }  DEFUN (no_debug_igmp, @@ -5378,10 +5833,10 @@ DEFUN (no_debug_igmp,         DEBUG_STR         DEBUG_IGMP_STR)  { -  PIM_DONT_DEBUG_IGMP_EVENTS; -  PIM_DONT_DEBUG_IGMP_PACKETS; -  PIM_DONT_DEBUG_IGMP_TRACE; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_IGMP_EVENTS; +	PIM_DONT_DEBUG_IGMP_PACKETS; +	PIM_DONT_DEBUG_IGMP_TRACE; +	return CMD_SUCCESS;  } @@ -5392,8 +5847,8 @@ DEFUN (debug_igmp_events,         DEBUG_IGMP_STR         DEBUG_IGMP_EVENTS_STR)  { -  PIM_DO_DEBUG_IGMP_EVENTS; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_IGMP_EVENTS; +	return CMD_SUCCESS;  }  DEFUN (no_debug_igmp_events, @@ -5404,8 +5859,8 @@ DEFUN (no_debug_igmp_events,         DEBUG_IGMP_STR         DEBUG_IGMP_EVENTS_STR)  { -  PIM_DONT_DEBUG_IGMP_EVENTS; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_IGMP_EVENTS; +	return CMD_SUCCESS;  } @@ -5416,8 +5871,8 @@ DEFUN (debug_igmp_packets,         DEBUG_IGMP_STR         DEBUG_IGMP_PACKETS_STR)  { -  PIM_DO_DEBUG_IGMP_PACKETS; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_IGMP_PACKETS; +	return CMD_SUCCESS;  }  DEFUN (no_debug_igmp_packets, @@ -5428,8 +5883,8 @@ DEFUN (no_debug_igmp_packets,         DEBUG_IGMP_STR         DEBUG_IGMP_PACKETS_STR)  { -  PIM_DONT_DEBUG_IGMP_PACKETS; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_IGMP_PACKETS; +	return CMD_SUCCESS;  } @@ -5440,8 +5895,8 @@ DEFUN (debug_igmp_trace,         DEBUG_IGMP_STR         DEBUG_IGMP_TRACE_STR)  { -  PIM_DO_DEBUG_IGMP_TRACE; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_IGMP_TRACE; +	return CMD_SUCCESS;  }  DEFUN (no_debug_igmp_trace, @@ -5452,8 +5907,8 @@ DEFUN (no_debug_igmp_trace,         DEBUG_IGMP_STR         DEBUG_IGMP_TRACE_STR)  { -  PIM_DONT_DEBUG_IGMP_TRACE; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_IGMP_TRACE; +	return CMD_SUCCESS;  } @@ -5463,8 +5918,8 @@ DEFUN (debug_mroute,         DEBUG_STR         DEBUG_MROUTE_STR)  { -  PIM_DO_DEBUG_MROUTE; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_MROUTE; +	return CMD_SUCCESS;  }  DEFUN (debug_mroute_detail, @@ -5474,8 +5929,8 @@ DEFUN (debug_mroute_detail,         DEBUG_MROUTE_STR         "detailed\n")  { -  PIM_DO_DEBUG_MROUTE_DETAIL; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_MROUTE_DETAIL; +	return CMD_SUCCESS;  }  DEFUN (no_debug_mroute, @@ -5485,8 +5940,8 @@ DEFUN (no_debug_mroute,         DEBUG_STR         DEBUG_MROUTE_STR)  { -  PIM_DONT_DEBUG_MROUTE; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_MROUTE; +	return CMD_SUCCESS;  }  DEFUN (no_debug_mroute_detail, @@ -5497,8 +5952,8 @@ DEFUN (no_debug_mroute_detail,         DEBUG_MROUTE_STR         "detailed\n")  { -  PIM_DONT_DEBUG_MROUTE_DETAIL; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_MROUTE_DETAIL; +	return CMD_SUCCESS;  }  DEFUN (debug_static, @@ -5507,8 +5962,8 @@ DEFUN (debug_static,         DEBUG_STR         DEBUG_STATIC_STR)  { -  PIM_DO_DEBUG_STATIC; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_STATIC; +	return CMD_SUCCESS;  }  DEFUN (no_debug_static, @@ -5518,8 +5973,8 @@ DEFUN (no_debug_static,         DEBUG_STR         DEBUG_STATIC_STR)  { -  PIM_DONT_DEBUG_STATIC; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_STATIC; +	return CMD_SUCCESS;  } @@ -5529,12 +5984,12 @@ DEFUN (debug_pim,         DEBUG_STR         DEBUG_PIM_STR)  { -  PIM_DO_DEBUG_PIM_EVENTS; -  PIM_DO_DEBUG_PIM_PACKETS; -  PIM_DO_DEBUG_PIM_TRACE; -  PIM_DO_DEBUG_MSDP_EVENTS; -  PIM_DO_DEBUG_MSDP_PACKETS; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_PIM_EVENTS; +	PIM_DO_DEBUG_PIM_PACKETS; +	PIM_DO_DEBUG_PIM_TRACE; +	PIM_DO_DEBUG_MSDP_EVENTS; +	PIM_DO_DEBUG_MSDP_PACKETS; +	return CMD_SUCCESS;  }  DEFUN (no_debug_pim, @@ -5544,16 +5999,16 @@ DEFUN (no_debug_pim,         DEBUG_STR         DEBUG_PIM_STR)  { -  PIM_DONT_DEBUG_PIM_EVENTS; -  PIM_DONT_DEBUG_PIM_PACKETS; -  PIM_DONT_DEBUG_PIM_TRACE; -  PIM_DONT_DEBUG_MSDP_EVENTS; -  PIM_DONT_DEBUG_MSDP_PACKETS; +	PIM_DONT_DEBUG_PIM_EVENTS; +	PIM_DONT_DEBUG_PIM_PACKETS; +	PIM_DONT_DEBUG_PIM_TRACE; +	PIM_DONT_DEBUG_MSDP_EVENTS; +	PIM_DONT_DEBUG_MSDP_PACKETS; -  PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; -  PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; +	PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; +	PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } @@ -5564,8 +6019,8 @@ DEFUN (debug_pim_events,         DEBUG_PIM_STR         DEBUG_PIM_EVENTS_STR)  { -  PIM_DO_DEBUG_PIM_EVENTS; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_PIM_EVENTS; +	return CMD_SUCCESS;  }  DEFUN (no_debug_pim_events, @@ -5576,8 +6031,8 @@ DEFUN (no_debug_pim_events,         DEBUG_PIM_STR         DEBUG_PIM_EVENTS_STR)  { -  PIM_DONT_DEBUG_PIM_EVENTS; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_PIM_EVENTS; +	return CMD_SUCCESS;  }  DEFUN (debug_pim_packets, @@ -5590,28 +6045,21 @@ DEFUN (debug_pim_packets,         DEBUG_PIM_J_P_PACKETS_STR         DEBUG_PIM_PIM_REG_PACKETS_STR)  { -  int idx = 0; -  if (argv_find (argv, argc, "hello", &idx)) -    { -      PIM_DO_DEBUG_PIM_HELLO; -      vty_out (vty, "PIM Hello debugging is on\n"); -    } -  else if (argv_find (argv, argc ,"joins", &idx)) -    { -      PIM_DO_DEBUG_PIM_J_P; -      vty_out (vty, "PIM Join/Prune debugging is on\n"); -    } -  else if (argv_find (argv, argc, "register", &idx)) -    { -      PIM_DO_DEBUG_PIM_REG; -      vty_out (vty, "PIM Register debugging is on\n"); -    } -  else -    { -      PIM_DO_DEBUG_PIM_PACKETS; -      vty_out (vty, "PIM Packet debugging is on \n"); -    } -  return CMD_SUCCESS; +	int idx = 0; +	if (argv_find(argv, argc, "hello", &idx)) { +		PIM_DO_DEBUG_PIM_HELLO; +		vty_out(vty, "PIM Hello debugging is on\n"); +	} else if (argv_find(argv, argc, "joins", &idx)) { +		PIM_DO_DEBUG_PIM_J_P; +		vty_out(vty, "PIM Join/Prune debugging is on\n"); +	} else if (argv_find(argv, argc, "register", &idx)) { +		PIM_DO_DEBUG_PIM_REG; +		vty_out(vty, "PIM Register debugging is on\n"); +	} else { +		PIM_DO_DEBUG_PIM_PACKETS; +		vty_out(vty, "PIM Packet debugging is on \n"); +	} +	return CMD_SUCCESS;  }  DEFUN (no_debug_pim_packets, @@ -5625,26 +6073,20 @@ DEFUN (no_debug_pim_packets,         DEBUG_PIM_J_P_PACKETS_STR         DEBUG_PIM_PIM_REG_PACKETS_STR)  { -  int idx = 0; -  if (argv_find (argv, argc,"hello",&idx)) -    { -      PIM_DONT_DEBUG_PIM_HELLO; -      vty_out (vty, "PIM Hello debugging is off \n"); -    } -  else if (argv_find (argv, argc, "joins", &idx)) -    { -      PIM_DONT_DEBUG_PIM_J_P; -      vty_out (vty, "PIM Join/Prune debugging is off \n"); -    } -  else if (argv_find (argv, argc, "register", &idx)) -    { -      PIM_DONT_DEBUG_PIM_REG; -      vty_out (vty, "PIM Register debugging is off\n"); -    } -  else -    PIM_DONT_DEBUG_PIM_PACKETS; - -  return CMD_SUCCESS; +	int idx = 0; +	if (argv_find(argv, argc, "hello", &idx)) { +		PIM_DONT_DEBUG_PIM_HELLO; +		vty_out(vty, "PIM Hello debugging is off \n"); +	} else if (argv_find(argv, argc, "joins", &idx)) { +		PIM_DONT_DEBUG_PIM_J_P; +		vty_out(vty, "PIM Join/Prune debugging is off \n"); +	} else if (argv_find(argv, argc, "register", &idx)) { +		PIM_DONT_DEBUG_PIM_REG; +		vty_out(vty, "PIM Register debugging is off\n"); +	} else +		PIM_DONT_DEBUG_PIM_PACKETS; + +	return CMD_SUCCESS;  } @@ -5656,8 +6098,8 @@ DEFUN (debug_pim_packetdump_send,         DEBUG_PIM_PACKETDUMP_STR         DEBUG_PIM_PACKETDUMP_SEND_STR)  { -  PIM_DO_DEBUG_PIM_PACKETDUMP_SEND; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_PIM_PACKETDUMP_SEND; +	return CMD_SUCCESS;  }  DEFUN (no_debug_pim_packetdump_send, @@ -5669,8 +6111,8 @@ DEFUN (no_debug_pim_packetdump_send,         DEBUG_PIM_PACKETDUMP_STR         DEBUG_PIM_PACKETDUMP_SEND_STR)  { -  PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; +	return CMD_SUCCESS;  } @@ -5682,8 +6124,8 @@ DEFUN (debug_pim_packetdump_recv,         DEBUG_PIM_PACKETDUMP_STR         DEBUG_PIM_PACKETDUMP_RECV_STR)  { -  PIM_DO_DEBUG_PIM_PACKETDUMP_RECV; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_PIM_PACKETDUMP_RECV; +	return CMD_SUCCESS;  }  DEFUN (no_debug_pim_packetdump_recv, @@ -5695,8 +6137,8 @@ DEFUN (no_debug_pim_packetdump_recv,         DEBUG_PIM_PACKETDUMP_STR         DEBUG_PIM_PACKETDUMP_RECV_STR)  { -  PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; +	return CMD_SUCCESS;  } @@ -5707,8 +6149,8 @@ DEFUN (debug_pim_trace,         DEBUG_PIM_STR         DEBUG_PIM_TRACE_STR)  { -  PIM_DO_DEBUG_PIM_TRACE; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_PIM_TRACE; +	return CMD_SUCCESS;  }  DEFUN (no_debug_pim_trace, @@ -5719,8 +6161,8 @@ DEFUN (no_debug_pim_trace,         DEBUG_PIM_STR         DEBUG_PIM_TRACE_STR)  { -  PIM_DONT_DEBUG_PIM_TRACE; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_PIM_TRACE; +	return CMD_SUCCESS;  } @@ -5730,8 +6172,8 @@ DEFUN (debug_ssmpingd,         DEBUG_STR         DEBUG_SSMPINGD_STR)  { -  PIM_DO_DEBUG_SSMPINGD; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_SSMPINGD; +	return CMD_SUCCESS;  }  DEFUN (no_debug_ssmpingd, @@ -5741,8 +6183,8 @@ DEFUN (no_debug_ssmpingd,         DEBUG_STR         DEBUG_SSMPINGD_STR)  { -  PIM_DONT_DEBUG_SSMPINGD; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_SSMPINGD; +	return CMD_SUCCESS;  } @@ -5753,8 +6195,8 @@ DEFUN (debug_pim_zebra,         DEBUG_PIM_STR         DEBUG_PIM_ZEBRA_STR)  { -  PIM_DO_DEBUG_ZEBRA; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_ZEBRA; +	return CMD_SUCCESS;  }  DEFUN (no_debug_pim_zebra, @@ -5765,8 +6207,8 @@ DEFUN (no_debug_pim_zebra,         DEBUG_PIM_STR         DEBUG_PIM_ZEBRA_STR)  { -  PIM_DONT_DEBUG_ZEBRA; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_ZEBRA; +	return CMD_SUCCESS;  } @@ -5776,9 +6218,9 @@ DEFUN (debug_msdp,         DEBUG_STR         DEBUG_MSDP_STR)  { -  PIM_DO_DEBUG_MSDP_EVENTS; -  PIM_DO_DEBUG_MSDP_PACKETS; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_MSDP_EVENTS; +	PIM_DO_DEBUG_MSDP_PACKETS; +	return CMD_SUCCESS;  }  DEFUN (no_debug_msdp, @@ -5788,16 +6230,13 @@ DEFUN (no_debug_msdp,         DEBUG_STR         DEBUG_MSDP_STR)  { -  PIM_DONT_DEBUG_MSDP_EVENTS; -  PIM_DONT_DEBUG_MSDP_PACKETS; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_MSDP_EVENTS; +	PIM_DONT_DEBUG_MSDP_PACKETS; +	return CMD_SUCCESS;  } -ALIAS (no_debug_msdp, -       undebug_msdp_cmd, -       "undebug msdp", -       UNDEBUG_STR -       DEBUG_MSDP_STR) +ALIAS(no_debug_msdp, undebug_msdp_cmd, "undebug msdp", +      UNDEBUG_STR DEBUG_MSDP_STR)  DEFUN (debug_msdp_events,         debug_msdp_events_cmd, @@ -5806,8 +6245,8 @@ DEFUN (debug_msdp_events,         DEBUG_MSDP_STR         DEBUG_MSDP_EVENTS_STR)  { -  PIM_DO_DEBUG_MSDP_EVENTS; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_MSDP_EVENTS; +	return CMD_SUCCESS;  }  DEFUN (no_debug_msdp_events, @@ -5818,16 +6257,12 @@ DEFUN (no_debug_msdp_events,         DEBUG_MSDP_STR         DEBUG_MSDP_EVENTS_STR)  { -  PIM_DONT_DEBUG_MSDP_EVENTS; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_MSDP_EVENTS; +	return CMD_SUCCESS;  } -ALIAS (no_debug_msdp_events, -       undebug_msdp_events_cmd, -       "undebug msdp events", -       UNDEBUG_STR -       DEBUG_MSDP_STR -       DEBUG_MSDP_EVENTS_STR) +ALIAS(no_debug_msdp_events, undebug_msdp_events_cmd, "undebug msdp events", +      UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR)  DEFUN (debug_msdp_packets,         debug_msdp_packets_cmd, @@ -5836,8 +6271,8 @@ DEFUN (debug_msdp_packets,         DEBUG_MSDP_STR         DEBUG_MSDP_PACKETS_STR)  { -  PIM_DO_DEBUG_MSDP_PACKETS; -  return CMD_SUCCESS; +	PIM_DO_DEBUG_MSDP_PACKETS; +	return CMD_SUCCESS;  }  DEFUN (no_debug_msdp_packets, @@ -5848,16 +6283,12 @@ DEFUN (no_debug_msdp_packets,         DEBUG_MSDP_STR         DEBUG_MSDP_PACKETS_STR)  { -  PIM_DONT_DEBUG_MSDP_PACKETS; -  return CMD_SUCCESS; +	PIM_DONT_DEBUG_MSDP_PACKETS; +	return CMD_SUCCESS;  } -ALIAS (no_debug_msdp_packets, -       undebug_msdp_packets_cmd, -       "undebug msdp packets", -       UNDEBUG_STR -       DEBUG_MSDP_STR -       DEBUG_MSDP_PACKETS_STR) +ALIAS(no_debug_msdp_packets, undebug_msdp_packets_cmd, "undebug msdp packets", +      UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR)  DEFUN (show_debugging_pim,         show_debugging_pim_cmd, @@ -5866,39 +6297,38 @@ DEFUN (show_debugging_pim,         DEBUG_STR         PIM_STR)  { -  pim_debug_config_write(vty); -  return CMD_SUCCESS; +	pim_debug_config_write(vty); +	return CMD_SUCCESS;  } -static int -interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) +static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)  { -  int result; -  struct in_addr source_addr; -  VTY_DECLVAR_CONTEXT(interface, ifp); +	int result; +	struct in_addr source_addr; +	VTY_DECLVAR_CONTEXT(interface, ifp); -  result = inet_pton(AF_INET, source, &source_addr); -  if (result <= 0) { -    vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", -        source, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = inet_pton(AF_INET, source, &source_addr); +	if (result <= 0) { +		vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -  result = pim_update_source_set(ifp, source_addr); -  switch (result) { -    case PIM_SUCCESS: -      break; -   case PIM_IFACE_NOT_FOUND: -      vty_out (vty, "Pim not enabled on this interface\n"); -      break; -    case PIM_UPDATE_SOURCE_DUP: -      vty_out (vty, "%% Source already set to %s\n", source); -      break; -    default: -      vty_out (vty, "%% Source set failed\n"); -  } +	result = pim_update_source_set(ifp, source_addr); +	switch (result) { +	case PIM_SUCCESS: +		break; +	case PIM_IFACE_NOT_FOUND: +		vty_out(vty, "Pim not enabled on this interface\n"); +		break; +	case PIM_UPDATE_SOURCE_DUP: +		vty_out(vty, "%% Source already set to %s\n", source); +		break; +	default: +		vty_out(vty, "%% Source set failed\n"); +	} -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  }  DEFUN (interface_pim_use_source, @@ -5909,7 +6339,7 @@ DEFUN (interface_pim_use_source,         "Configure primary IP address\n"         "source ip address\n")  { -  return interface_pim_use_src_cmd_worker (vty, argv[3]->arg); +	return interface_pim_use_src_cmd_worker(vty, argv[3]->arg);  }  DEFUN (interface_no_pim_use_source, @@ -5920,7 +6350,7 @@ DEFUN (interface_no_pim_use_source,         "pim multicast routing\n"         "Delete source IP address\n")  { -  return interface_pim_use_src_cmd_worker (vty, "0.0.0.0"); +	return interface_pim_use_src_cmd_worker(vty, "0.0.0.0");  }  DEFUN (ip_pim_bfd, @@ -5930,19 +6360,19 @@ DEFUN (ip_pim_bfd,         PIM_STR         "Enables BFD support\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; -  struct bfd_info *bfd_info = NULL; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; +	struct bfd_info *bfd_info = NULL; -  if (!pim_ifp) -    return CMD_SUCCESS; -  bfd_info = pim_ifp->bfd_info; +	if (!pim_ifp) +		return CMD_SUCCESS; +	bfd_info = pim_ifp->bfd_info; -  if (!bfd_info || !CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) -    pim_bfd_if_param_set (ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, -                          BFD_DEF_DETECT_MULT, 1); +	if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) +		pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, +				     BFD_DEF_DETECT_MULT, 1); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (no_ip_pim_bfd, @@ -5953,19 +6383,18 @@ DEFUN (no_ip_pim_bfd,         PIM_STR         "Disables BFD support\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  struct pim_interface *pim_ifp = ifp->info; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) -    return CMD_SUCCESS; +	if (!pim_ifp) +		return CMD_SUCCESS; -  if (pim_ifp->bfd_info) -    { -      pim_bfd_reg_dereg_all_nbr (ifp, ZEBRA_BFD_DEST_DEREGISTER); -      bfd_info_free (&(pim_ifp->bfd_info)); -    } +	if (pim_ifp->bfd_info) { +		pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER); +		bfd_info_free(&(pim_ifp->bfd_info)); +	} -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  DEFUN (ip_pim_bfd_param, @@ -5978,77 +6407,74 @@ DEFUN (ip_pim_bfd_param,         "Required min receive interval\n"         "Desired min transmit interval\n")  { -  VTY_DECLVAR_CONTEXT(interface, ifp); -  int idx_number = 3; -  int idx_number_2 = 4; -  int idx_number_3 = 5; -  u_int32_t rx_val; -  u_int32_t tx_val; -  u_int8_t dm_val; -  int ret; +	VTY_DECLVAR_CONTEXT(interface, ifp); +	int idx_number = 3; +	int idx_number_2 = 4; +	int idx_number_3 = 5; +	u_int32_t rx_val; +	u_int32_t tx_val; +	u_int8_t dm_val; +	int ret; -  if ((ret = bfd_validate_param (vty, argv[idx_number]->arg, -                                 argv[idx_number_2]->arg, -                                 argv[idx_number_3]->arg, -                                 &dm_val, &rx_val, &tx_val)) != CMD_SUCCESS) -    return ret; +	if ((ret = bfd_validate_param( +		     vty, argv[idx_number]->arg, argv[idx_number_2]->arg, +		     argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val)) +	    != CMD_SUCCESS) +		return ret; -  pim_bfd_if_param_set (ifp, rx_val, tx_val, dm_val, 0); +	pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -ALIAS (no_ip_pim_bfd, -       no_ip_pim_bfd_param_cmd, -       "no ip pim bfd (2-255) (50-60000) (50-60000)", -       NO_STR -       IP_STR -       PIM_STR -       "Enables BFD support\n" -       "Detect Multiplier\n" -       "Required min receive interval\n" -       "Desired min transmit interval\n") +ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd, +      "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR +      "Enables BFD support\n" +      "Detect Multiplier\n" +      "Required min receive interval\n" +      "Desired min transmit interval\n") + +static int ip_msdp_peer_cmd_worker(struct vty *vty, const char *peer, +				   const char *local) +{ +	enum pim_msdp_err result; +	struct in_addr peer_addr; +	struct in_addr local_addr; + +	result = inet_pton(AF_INET, peer, &peer_addr); +	if (result <= 0) { +		vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	result = inet_pton(AF_INET, local, &local_addr); +	if (result <= 0) { +		vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -static int -ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local) -{ -  enum pim_msdp_err result; -  struct in_addr peer_addr; -  struct in_addr local_addr; - -  result = inet_pton(AF_INET, peer, &peer_addr); -  if (result <= 0) { -    vty_out (vty, "%% Bad peer address %s: errno=%d: %s\n", -        peer, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  result = inet_pton(AF_INET, local, &local_addr); -  if (result <= 0) { -    vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", -        local, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } - -  result = pim_msdp_peer_add(peer_addr, local_addr, "default", NULL/* mp_p */); -  switch (result) { -    case PIM_MSDP_ERR_NONE: -      break; -    case PIM_MSDP_ERR_OOM: -      vty_out (vty, "%% Out of memory\n"); -      break; -    case PIM_MSDP_ERR_PEER_EXISTS: -      vty_out (vty, "%% Peer exists\n"); -      break; -    case PIM_MSDP_ERR_MAX_MESH_GROUPS: -      vty_out (vty, "%% Only one mesh-group allowed currently\n"); -      break; -    default: -      vty_out (vty, "%% peer add failed\n"); -  } - -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	result = pim_msdp_peer_add(peer_addr, local_addr, "default", +				   NULL /* mp_p */); +	switch (result) { +	case PIM_MSDP_ERR_NONE: +		break; +	case PIM_MSDP_ERR_OOM: +		vty_out(vty, "%% Out of memory\n"); +		break; +	case PIM_MSDP_ERR_PEER_EXISTS: +		vty_out(vty, "%% Peer exists\n"); +		break; +	case PIM_MSDP_ERR_MAX_MESH_GROUPS: +		vty_out(vty, "%% Only one mesh-group allowed currently\n"); +		break; +	default: +		vty_out(vty, "%% peer add failed\n"); +	} + +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  }  DEFUN_HIDDEN (ip_msdp_peer, @@ -6061,34 +6487,33 @@ DEFUN_HIDDEN (ip_msdp_peer,         "Source address for TCP connection\n"         "local ip address\n")  { -  return ip_msdp_peer_cmd_worker (vty, argv[3]->arg, argv[5]->arg); +	return ip_msdp_peer_cmd_worker(vty, argv[3]->arg, argv[5]->arg);  } -static int -ip_no_msdp_peer_cmd_worker (struct vty *vty, const char *peer) +static int ip_no_msdp_peer_cmd_worker(struct vty *vty, const char *peer)  { -  enum pim_msdp_err result; -  struct in_addr peer_addr; +	enum pim_msdp_err result; +	struct in_addr peer_addr; -  result = inet_pton(AF_INET, peer, &peer_addr); -  if (result <= 0) { -    vty_out (vty, "%% Bad peer address %s: errno=%d: %s\n", -        peer, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = inet_pton(AF_INET, peer, &peer_addr); +	if (result <= 0) { +		vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -  result = pim_msdp_peer_del(peer_addr); -  switch (result) { -    case PIM_MSDP_ERR_NONE: -      break; -    case PIM_MSDP_ERR_NO_PEER: -      vty_out (vty, "%% Peer does not exist\n"); -      break; -    default: -      vty_out (vty, "%% peer del failed\n"); -  } +	result = pim_msdp_peer_del(peer_addr); +	switch (result) { +	case PIM_MSDP_ERR_NONE: +		break; +	case PIM_MSDP_ERR_NO_PEER: +		vty_out(vty, "%% Peer does not exist\n"); +		break; +	default: +		vty_out(vty, "%% peer del failed\n"); +	} -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  }  DEFUN_HIDDEN (no_ip_msdp_peer, @@ -6100,40 +6525,40 @@ DEFUN_HIDDEN (no_ip_msdp_peer,         "Delete MSDP peer\n"         "peer ip address\n")  { -  return ip_no_msdp_peer_cmd_worker (vty, argv[4]->arg); +	return ip_no_msdp_peer_cmd_worker(vty, argv[4]->arg);  } -static int -ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +static int ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, +						const char *mbr)  { -  enum pim_msdp_err result; -  struct in_addr mbr_ip; +	enum pim_msdp_err result; +	struct in_addr mbr_ip; -  result = inet_pton(AF_INET, mbr, &mbr_ip); -  if (result <= 0) { -    vty_out (vty, "%% Bad member address %s: errno=%d: %s\n", -        mbr, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = inet_pton(AF_INET, mbr, &mbr_ip); +	if (result <= 0) { +		vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -  result = pim_msdp_mg_mbr_add(mg, mbr_ip); -  switch (result) { -    case PIM_MSDP_ERR_NONE: -      break; -    case PIM_MSDP_ERR_OOM: -      vty_out (vty, "%% Out of memory\n"); -      break; -    case PIM_MSDP_ERR_MG_MBR_EXISTS: -      vty_out (vty, "%% mesh-group member exists\n"); -      break; -    case PIM_MSDP_ERR_MAX_MESH_GROUPS: -      vty_out (vty, "%% Only one mesh-group allowed currently\n"); -      break; -    default: -      vty_out (vty, "%% member add failed\n"); -  } +	result = pim_msdp_mg_mbr_add(mg, mbr_ip); +	switch (result) { +	case PIM_MSDP_ERR_NONE: +		break; +	case PIM_MSDP_ERR_OOM: +		vty_out(vty, "%% Out of memory\n"); +		break; +	case PIM_MSDP_ERR_MG_MBR_EXISTS: +		vty_out(vty, "%% mesh-group member exists\n"); +		break; +	case PIM_MSDP_ERR_MAX_MESH_GROUPS: +		vty_out(vty, "%% Only one mesh-group allowed currently\n"); +		break; +	default: +		vty_out(vty, "%% member add failed\n"); +	} -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  }  DEFUN (ip_msdp_mesh_group_member, @@ -6146,37 +6571,39 @@ DEFUN (ip_msdp_mesh_group_member,         "mesh group member\n"         "peer ip address\n")  { -  return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg, argv[5]->arg); +	return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg, +						    argv[5]->arg);  } -static int -ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +static int ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty, +						   const char *mg, +						   const char *mbr)  { -  enum pim_msdp_err result; -  struct in_addr mbr_ip; +	enum pim_msdp_err result; +	struct in_addr mbr_ip; -  result = inet_pton(AF_INET, mbr, &mbr_ip); -  if (result <= 0) { -    vty_out (vty, "%% Bad member address %s: errno=%d: %s\n", -        mbr, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = inet_pton(AF_INET, mbr, &mbr_ip); +	if (result <= 0) { +		vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -  result = pim_msdp_mg_mbr_del(mg, mbr_ip); -  switch (result) { -    case PIM_MSDP_ERR_NONE: -      break; -    case PIM_MSDP_ERR_NO_MG: -      vty_out (vty, "%% mesh-group does not exist\n"); -      break; -    case PIM_MSDP_ERR_NO_MG_MBR: -      vty_out (vty, "%% mesh-group member does not exist\n"); -      break; -    default: -      vty_out (vty, "%% mesh-group member del failed\n"); -  } +	result = pim_msdp_mg_mbr_del(mg, mbr_ip); +	switch (result) { +	case PIM_MSDP_ERR_NONE: +		break; +	case PIM_MSDP_ERR_NO_MG: +		vty_out(vty, "%% mesh-group does not exist\n"); +		break; +	case PIM_MSDP_ERR_NO_MG_MBR: +		vty_out(vty, "%% mesh-group member does not exist\n"); +		break; +	default: +		vty_out(vty, "%% mesh-group member del failed\n"); +	} -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  }  DEFUN (no_ip_msdp_mesh_group_member,         no_ip_msdp_mesh_group_member_cmd, @@ -6189,37 +6616,38 @@ DEFUN (no_ip_msdp_mesh_group_member,         "mesh group member\n"         "peer ip address\n")  { -  return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg, argv[6]->arg); +	return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg, +						       argv[6]->arg);  } -static int -ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg, const char *src) +static int ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg, +						const char *src)  { -  enum pim_msdp_err result; -  struct in_addr src_ip; +	enum pim_msdp_err result; +	struct in_addr src_ip; -  result = inet_pton(AF_INET, src, &src_ip); -  if (result <= 0) { -    vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", -        src, errno, safe_strerror(errno)); -    return CMD_WARNING_CONFIG_FAILED; -  } +	result = inet_pton(AF_INET, src, &src_ip); +	if (result <= 0) { +		vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src, +			errno, safe_strerror(errno)); +		return CMD_WARNING_CONFIG_FAILED; +	} -  result = pim_msdp_mg_src_add(mg, src_ip); -  switch (result) { -    case PIM_MSDP_ERR_NONE: -      break; -    case PIM_MSDP_ERR_OOM: -      vty_out (vty, "%% Out of memory\n"); -      break; -    case PIM_MSDP_ERR_MAX_MESH_GROUPS: -      vty_out (vty, "%% Only one mesh-group allowed currently\n"); -      break; -    default: -      vty_out (vty, "%% source add failed\n"); -  } +	result = pim_msdp_mg_src_add(mg, src_ip); +	switch (result) { +	case PIM_MSDP_ERR_NONE: +		break; +	case PIM_MSDP_ERR_OOM: +		vty_out(vty, "%% Out of memory\n"); +		break; +	case PIM_MSDP_ERR_MAX_MESH_GROUPS: +		vty_out(vty, "%% Only one mesh-group allowed currently\n"); +		break; +	default: +		vty_out(vty, "%% source add failed\n"); +	} -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  } @@ -6233,45 +6661,45 @@ DEFUN (ip_msdp_mesh_group_source,         "mesh group local address\n"         "source ip address for the TCP connection\n")  { -  return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg, argv[5]->arg); +	return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg, +						    argv[5]->arg);  } -static int -ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg) +static int ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, +						   const char *mg)  { -  enum pim_msdp_err result; +	enum pim_msdp_err result; -  result = pim_msdp_mg_src_del(mg); -  switch (result) { -    case PIM_MSDP_ERR_NONE: -      break; -    case PIM_MSDP_ERR_NO_MG: -      vty_out (vty, "%% mesh-group does not exist\n"); -      break; -    default: -      vty_out (vty, "%% mesh-group source del failed\n"); -  } +	result = pim_msdp_mg_src_del(mg); +	switch (result) { +	case PIM_MSDP_ERR_NONE: +		break; +	case PIM_MSDP_ERR_NO_MG: +		vty_out(vty, "%% mesh-group does not exist\n"); +		break; +	default: +		vty_out(vty, "%% mesh-group source del failed\n"); +	} -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  } -static int -ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) +static int ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg)  { -  enum pim_msdp_err result; +	enum pim_msdp_err result; -  result = pim_msdp_mg_del(mg); -  switch (result) { -    case PIM_MSDP_ERR_NONE: -      break; -    case PIM_MSDP_ERR_NO_MG: -      vty_out (vty, "%% mesh-group does not exist\n"); -      break; -    default: -      vty_out (vty, "%% mesh-group source del failed\n"); -  } +	result = pim_msdp_mg_del(mg); +	switch (result) { +	case PIM_MSDP_ERR_NONE: +		break; +	case PIM_MSDP_ERR_NO_MG: +		vty_out(vty, "%% mesh-group does not exist\n"); +		break; +	default: +		vty_out(vty, "%% mesh-group source del failed\n"); +	} -  return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; +	return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;  }  DEFUN (no_ip_msdp_mesh_group_source, @@ -6285,86 +6713,87 @@ DEFUN (no_ip_msdp_mesh_group_source,         "mesh group source\n"         "mesh group local address\n")  { -  if (argc == 7) -    return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); -  else -    return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg); -} - -static void -print_empty_json_obj(struct vty *vty) -{ -  json_object *json; -  json = json_object_new_object(); -  vty_out (vty, "%s\n", -             json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -  json_object_free(json); -} - -static void -ip_msdp_show_mesh_group(struct vty *vty, u_char uj) -{ -  struct listnode *mbrnode; -  struct pim_msdp_mg_mbr *mbr; -  struct pim_msdp_mg *mg = msdp->mg; -  char mbr_str[INET_ADDRSTRLEN]; -  char src_str[INET_ADDRSTRLEN]; -  char state_str[PIM_MSDP_STATE_STRLEN]; -  enum pim_msdp_peer_state state; -  json_object *json = NULL; -  json_object *json_mg_row = NULL; -  json_object *json_members = NULL; -  json_object *json_row = NULL; - -  if (!mg) { -    if (uj) -      print_empty_json_obj(vty); -    return; -  } - -  pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str)); -  if (uj) { -    json = json_object_new_object(); -    /* currently there is only one mesh group but we should still make -     * it a dict with mg-name as key */ -    json_mg_row = json_object_new_object(); -    json_object_string_add(json_mg_row, "name", mg->mesh_group_name); -    json_object_string_add(json_mg_row, "source", src_str); -  } else { -    vty_out (vty, "Mesh group : %s\n", mg->mesh_group_name); -    vty_out (vty, "  Source : %s\n", src_str); -    vty_out (vty, "  Member                 State\n"); -  } - -  for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { -    pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); -    if (mbr->mp) { -      state = mbr->mp->state; -    } else { -      state = PIM_MSDP_DISABLED; -    } -    pim_msdp_state_dump(state, state_str, sizeof(state_str)); -    if (uj) { -      json_row = json_object_new_object(); -      json_object_string_add(json_row, "member", mbr_str); -      json_object_string_add(json_row, "state", state_str); -      if (!json_members) { -        json_members = json_object_new_object(); -        json_object_object_add(json_mg_row, "members", json_members); -      } -      json_object_object_add(json_members, mbr_str, json_row); -    } else { -      vty_out (vty, "  %-15s  %11s\n", -          mbr_str, state_str); -    } -  } - -  if (uj) { -    json_object_object_add(json, mg->mesh_group_name, json_mg_row); -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	if (argc == 7) +		return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); +	else +		return ip_no_msdp_mesh_group_source_cmd_worker(vty, +							       argv[4]->arg); +} + +static void print_empty_json_obj(struct vty *vty) +{ +	json_object *json; +	json = json_object_new_object(); +	vty_out(vty, "%s\n", +		json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); +	json_object_free(json); +} + +static void ip_msdp_show_mesh_group(struct vty *vty, u_char uj) +{ +	struct listnode *mbrnode; +	struct pim_msdp_mg_mbr *mbr; +	struct pim_msdp_mg *mg = msdp->mg; +	char mbr_str[INET_ADDRSTRLEN]; +	char src_str[INET_ADDRSTRLEN]; +	char state_str[PIM_MSDP_STATE_STRLEN]; +	enum pim_msdp_peer_state state; +	json_object *json = NULL; +	json_object *json_mg_row = NULL; +	json_object *json_members = NULL; +	json_object *json_row = NULL; + +	if (!mg) { +		if (uj) +			print_empty_json_obj(vty); +		return; +	} + +	pim_inet4_dump("<source?>", mg->src_ip, src_str, sizeof(src_str)); +	if (uj) { +		json = json_object_new_object(); +		/* currently there is only one mesh group but we should still +		 * make +		 * it a dict with mg-name as key */ +		json_mg_row = json_object_new_object(); +		json_object_string_add(json_mg_row, "name", +				       mg->mesh_group_name); +		json_object_string_add(json_mg_row, "source", src_str); +	} else { +		vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name); +		vty_out(vty, "  Source : %s\n", src_str); +		vty_out(vty, "  Member                 State\n"); +	} + +	for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { +		pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); +		if (mbr->mp) { +			state = mbr->mp->state; +		} else { +			state = PIM_MSDP_DISABLED; +		} +		pim_msdp_state_dump(state, state_str, sizeof(state_str)); +		if (uj) { +			json_row = json_object_new_object(); +			json_object_string_add(json_row, "member", mbr_str); +			json_object_string_add(json_row, "state", state_str); +			if (!json_members) { +				json_members = json_object_new_object(); +				json_object_object_add(json_mg_row, "members", +						       json_members); +			} +			json_object_object_add(json_members, mbr_str, json_row); +		} else { +			vty_out(vty, "  %-15s  %11s\n", mbr_str, state_str); +		} +	} + +	if (uj) { +		json_object_object_add(json, mg->mesh_group_name, json_mg_row); +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  DEFUN (show_ip_msdp_mesh_group, @@ -6376,151 +6805,168 @@ DEFUN (show_ip_msdp_mesh_group,         "MSDP mesh-group information\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  ip_msdp_show_mesh_group(vty, uj); - -  return CMD_SUCCESS; -} - -static void -ip_msdp_show_peers(struct vty *vty, u_char uj) -{ -  struct listnode *mpnode; -  struct pim_msdp_peer *mp; -  char peer_str[INET_ADDRSTRLEN]; -  char local_str[INET_ADDRSTRLEN]; -  char state_str[PIM_MSDP_STATE_STRLEN]; -  char timebuf[PIM_MSDP_UPTIME_STRLEN]; -  int64_t now; -  json_object *json = NULL; -  json_object *json_row = NULL; - - -  if (uj) { -    json = json_object_new_object(); -  } else { -    vty_out (vty, -              "Peer                       Local        State    Uptime   SaCnt\n"); -  } - -  for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { -    if (mp->state == PIM_MSDP_ESTABLISHED) { -      now = pim_time_monotonic_sec(); -      pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); -    } else { -      strcpy(timebuf, "-"); -    } -    pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); -    pim_inet4_dump("<local?>", mp->local, local_str, sizeof(local_str)); -    pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); -    if (uj) { -      json_row = json_object_new_object(); -      json_object_string_add(json_row, "peer", peer_str); -      json_object_string_add(json_row, "local", local_str); -      json_object_string_add(json_row, "state", state_str); -      json_object_string_add(json_row, "upTime", timebuf); -      json_object_int_add(json_row, "saCount", mp->sa_cnt); -      json_object_object_add(json, peer_str, json_row); -    } else { -      vty_out (vty, "%-15s  %15s  %11s  %8s  %6d\n", -          peer_str, local_str, state_str, -          timebuf, mp->sa_cnt); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } -} - -static void -ip_msdp_show_peers_detail(struct vty *vty, const char *peer, u_char uj) -{ -  struct listnode *mpnode; -  struct pim_msdp_peer *mp; -  char peer_str[INET_ADDRSTRLEN]; -  char local_str[INET_ADDRSTRLEN]; -  char state_str[PIM_MSDP_STATE_STRLEN]; -  char timebuf[PIM_MSDP_UPTIME_STRLEN]; -  char katimer[PIM_MSDP_TIMER_STRLEN]; -  char crtimer[PIM_MSDP_TIMER_STRLEN]; -  char holdtimer[PIM_MSDP_TIMER_STRLEN]; -  int64_t now; -  json_object *json = NULL; -  json_object *json_row = NULL; - -  if (uj) { -    json = json_object_new_object(); -  } - -  for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { -    pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); -    if (strcmp(peer, "detail") && -        strcmp(peer, peer_str)) -      continue; - -    if (mp->state == PIM_MSDP_ESTABLISHED) { -      now = pim_time_monotonic_sec(); -      pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); -    } else { -      strcpy(timebuf, "-"); -    } -    pim_inet4_dump("<local?>", mp->local, local_str, sizeof(local_str)); -    pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); -    pim_time_timer_to_hhmmss(katimer, sizeof(katimer), mp->ka_timer); -    pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), mp->cr_timer); -    pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), mp->hold_timer); - -    if (uj) { -      json_row = json_object_new_object(); -      json_object_string_add(json_row, "peer", peer_str); -      json_object_string_add(json_row, "local", local_str); -      json_object_string_add(json_row, "meshGroupName", mp->mesh_group_name); -      json_object_string_add(json_row, "state", state_str); -      json_object_string_add(json_row, "upTime", timebuf); -      json_object_string_add(json_row, "keepAliveTimer", katimer); -      json_object_string_add(json_row, "connRetryTimer", crtimer); -      json_object_string_add(json_row, "holdTimer", holdtimer); -      json_object_string_add(json_row, "lastReset", mp->last_reset); -      json_object_int_add(json_row, "connAttempts", mp->conn_attempts); -      json_object_int_add(json_row, "establishedChanges", mp->est_flaps); -      json_object_int_add(json_row, "saCount", mp->sa_cnt); -      json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); -      json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); -      json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); -      json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); -      json_object_object_add(json, peer_str, json_row); -    } else { -      vty_out (vty, "Peer : %s\n", peer_str); -      vty_out (vty, "  Local               : %s\n", local_str); -      vty_out (vty, "  Mesh Group          : %s\n", mp->mesh_group_name); -      vty_out (vty, "  State               : %s\n", state_str); -      vty_out (vty, "  Uptime              : %s\n", timebuf); - -      vty_out (vty, "  Keepalive Timer     : %s\n", katimer); -      vty_out (vty, "  Conn Retry Timer    : %s\n", crtimer); -      vty_out (vty, "  Hold Timer          : %s\n", holdtimer); -      vty_out (vty, "  Last Reset          : %s\n", mp->last_reset); -      vty_out (vty, "  Conn Attempts       : %d\n", mp->conn_attempts); -      vty_out (vty, "  Established Changes : %d\n", mp->est_flaps); -      vty_out (vty, "  SA Count            : %d\n", mp->sa_cnt); -      vty_out (vty, "  Statistics          :\n"); -      vty_out (vty, "                       Sent       Rcvd\n"); -      vty_out (vty, "    Keepalives : %10d %10d\n", -          mp->ka_tx_cnt, mp->ka_rx_cnt); -      vty_out (vty, "    SAs        : %10d %10d\n", -          mp->sa_tx_cnt, mp->sa_rx_cnt); -      vty_out (vty, "\n"); -    } -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	u_char uj = use_json(argc, argv); +	ip_msdp_show_mesh_group(vty, uj); + +	return CMD_SUCCESS; +} + +static void ip_msdp_show_peers(struct vty *vty, u_char uj) +{ +	struct listnode *mpnode; +	struct pim_msdp_peer *mp; +	char peer_str[INET_ADDRSTRLEN]; +	char local_str[INET_ADDRSTRLEN]; +	char state_str[PIM_MSDP_STATE_STRLEN]; +	char timebuf[PIM_MSDP_UPTIME_STRLEN]; +	int64_t now; +	json_object *json = NULL; +	json_object *json_row = NULL; + + +	if (uj) { +		json = json_object_new_object(); +	} else { +		vty_out(vty, +			"Peer                       Local        State    Uptime   SaCnt\n"); +	} + +	for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { +		if (mp->state == PIM_MSDP_ESTABLISHED) { +			now = pim_time_monotonic_sec(); +			pim_time_uptime(timebuf, sizeof(timebuf), +					now - mp->uptime); +		} else { +			strcpy(timebuf, "-"); +		} +		pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); +		pim_inet4_dump("<local?>", mp->local, local_str, +			       sizeof(local_str)); +		pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); +		if (uj) { +			json_row = json_object_new_object(); +			json_object_string_add(json_row, "peer", peer_str); +			json_object_string_add(json_row, "local", local_str); +			json_object_string_add(json_row, "state", state_str); +			json_object_string_add(json_row, "upTime", timebuf); +			json_object_int_add(json_row, "saCount", mp->sa_cnt); +			json_object_object_add(json, peer_str, json_row); +		} else { +			vty_out(vty, "%-15s  %15s  %11s  %8s  %6d\n", peer_str, +				local_str, state_str, timebuf, mp->sa_cnt); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} +} + +static void ip_msdp_show_peers_detail(struct vty *vty, const char *peer, +				      u_char uj) +{ +	struct listnode *mpnode; +	struct pim_msdp_peer *mp; +	char peer_str[INET_ADDRSTRLEN]; +	char local_str[INET_ADDRSTRLEN]; +	char state_str[PIM_MSDP_STATE_STRLEN]; +	char timebuf[PIM_MSDP_UPTIME_STRLEN]; +	char katimer[PIM_MSDP_TIMER_STRLEN]; +	char crtimer[PIM_MSDP_TIMER_STRLEN]; +	char holdtimer[PIM_MSDP_TIMER_STRLEN]; +	int64_t now; +	json_object *json = NULL; +	json_object *json_row = NULL; + +	if (uj) { +		json = json_object_new_object(); +	} + +	for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { +		pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); +		if (strcmp(peer, "detail") && strcmp(peer, peer_str)) +			continue; + +		if (mp->state == PIM_MSDP_ESTABLISHED) { +			now = pim_time_monotonic_sec(); +			pim_time_uptime(timebuf, sizeof(timebuf), +					now - mp->uptime); +		} else { +			strcpy(timebuf, "-"); +		} +		pim_inet4_dump("<local?>", mp->local, local_str, +			       sizeof(local_str)); +		pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); +		pim_time_timer_to_hhmmss(katimer, sizeof(katimer), +					 mp->ka_timer); +		pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), +					 mp->cr_timer); +		pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), +					 mp->hold_timer); + +		if (uj) { +			json_row = json_object_new_object(); +			json_object_string_add(json_row, "peer", peer_str); +			json_object_string_add(json_row, "local", local_str); +			json_object_string_add(json_row, "meshGroupName", +					       mp->mesh_group_name); +			json_object_string_add(json_row, "state", state_str); +			json_object_string_add(json_row, "upTime", timebuf); +			json_object_string_add(json_row, "keepAliveTimer", +					       katimer); +			json_object_string_add(json_row, "connRetryTimer", +					       crtimer); +			json_object_string_add(json_row, "holdTimer", +					       holdtimer); +			json_object_string_add(json_row, "lastReset", +					       mp->last_reset); +			json_object_int_add(json_row, "connAttempts", +					    mp->conn_attempts); +			json_object_int_add(json_row, "establishedChanges", +					    mp->est_flaps); +			json_object_int_add(json_row, "saCount", mp->sa_cnt); +			json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); +			json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); +			json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); +			json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); +			json_object_object_add(json, peer_str, json_row); +		} else { +			vty_out(vty, "Peer : %s\n", peer_str); +			vty_out(vty, "  Local               : %s\n", local_str); +			vty_out(vty, "  Mesh Group          : %s\n", +				mp->mesh_group_name); +			vty_out(vty, "  State               : %s\n", state_str); +			vty_out(vty, "  Uptime              : %s\n", timebuf); + +			vty_out(vty, "  Keepalive Timer     : %s\n", katimer); +			vty_out(vty, "  Conn Retry Timer    : %s\n", crtimer); +			vty_out(vty, "  Hold Timer          : %s\n", holdtimer); +			vty_out(vty, "  Last Reset          : %s\n", +				mp->last_reset); +			vty_out(vty, "  Conn Attempts       : %d\n", +				mp->conn_attempts); +			vty_out(vty, "  Established Changes : %d\n", +				mp->est_flaps); +			vty_out(vty, "  SA Count            : %d\n", +				mp->sa_cnt); +			vty_out(vty, "  Statistics          :\n"); +			vty_out(vty, +				"                       Sent       Rcvd\n"); +			vty_out(vty, "    Keepalives : %10d %10d\n", +				mp->ka_tx_cnt, mp->ka_rx_cnt); +			vty_out(vty, "    SAs        : %10d %10d\n", +				mp->sa_tx_cnt, mp->sa_rx_cnt); +			vty_out(vty, "\n"); +		} +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  DEFUN (show_ip_msdp_peer_detail, @@ -6534,181 +6980,183 @@ DEFUN (show_ip_msdp_peer_detail,         "peer ip address\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  if (uj) -    argc--; - -  if (argc > 4) -    ip_msdp_show_peers_detail(vty, argv[4]->arg, uj); -  else -    ip_msdp_show_peers(vty, uj); - -  return CMD_SUCCESS; -} - -static void -ip_msdp_show_sa(struct vty *vty, u_char uj) -{ -  struct listnode *sanode; -  struct pim_msdp_sa *sa; -  char src_str[INET_ADDRSTRLEN]; -  char grp_str[INET_ADDRSTRLEN]; -  char rp_str[INET_ADDRSTRLEN]; -  char timebuf[PIM_MSDP_UPTIME_STRLEN]; -  char spt_str[8]; -  char local_str[8]; -  int64_t now; -  json_object *json = NULL; -  json_object *json_group = NULL; -  json_object *json_row = NULL; - -  if (uj) { -    json = json_object_new_object(); -  } else { -    vty_out (vty, -              "Source                     Group               RP  Local  SPT    Uptime\n"); -  } - -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    now = pim_time_monotonic_sec(); -    pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); -    pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); -    if (sa->flags & PIM_MSDP_SAF_PEER) { -      pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); -      if (sa->up) { -        strcpy(spt_str, "yes"); -      } else { -        strcpy(spt_str, "no"); -      } -    } else { -      strcpy(rp_str, "-"); -      strcpy(spt_str, "-"); -    } -    if (sa->flags & PIM_MSDP_SAF_LOCAL) { -      strcpy(local_str, "yes"); -    } else { -      strcpy(local_str, "no"); -    } -    if (uj) { -      json_object_object_get_ex(json, grp_str, &json_group); - -      if (!json_group) { -        json_group = json_object_new_object(); -        json_object_object_add(json, grp_str, json_group); -      } - -      json_row = json_object_new_object(); -      json_object_string_add(json_row, "source", src_str); -      json_object_string_add(json_row, "group", grp_str); -      json_object_string_add(json_row, "rp", rp_str); -      json_object_string_add(json_row, "local", local_str); -      json_object_string_add(json_row, "sptSetup", spt_str); -      json_object_string_add(json_row, "upTime", timebuf); -      json_object_object_add(json_group, src_str, json_row); -    } else { -      vty_out (vty, "%-15s  %15s  %15s  %5c  %3c  %8s\n", -          src_str, grp_str, rp_str, local_str[0], spt_str[0], timebuf); -    } -  } - - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } -} - -static void -ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, -                             const char *grp_str, struct vty *vty, -                             u_char uj, json_object *json) -{ -  char rp_str[INET_ADDRSTRLEN]; -  char peer_str[INET_ADDRSTRLEN]; -  char timebuf[PIM_MSDP_UPTIME_STRLEN]; -  char spt_str[8]; -  char local_str[8]; -  char statetimer[PIM_MSDP_TIMER_STRLEN]; -  int64_t now; -  json_object *json_group = NULL; -  json_object *json_row = NULL; - -  now = pim_time_monotonic_sec(); -  pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); -  if (sa->flags & PIM_MSDP_SAF_PEER) { -    pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); -    pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str)); -    if (sa->up) { -      strcpy(spt_str, "yes"); -    } else { -      strcpy(spt_str, "no"); -    } -  } else { -    strcpy(rp_str, "-"); -    strcpy(peer_str, "-"); -    strcpy(spt_str, "-"); -  } -  if (sa->flags & PIM_MSDP_SAF_LOCAL) { -      strcpy(local_str, "yes"); -  } else { -      strcpy(local_str, "no"); -  } -  pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), sa->sa_state_timer); -  if (uj) { -    json_object_object_get_ex(json, grp_str, &json_group); - -    if (!json_group) { -      json_group = json_object_new_object(); -      json_object_object_add(json, grp_str, json_group); -    } - -    json_row = json_object_new_object(); -    json_object_string_add(json_row, "source", src_str); -    json_object_string_add(json_row, "group", grp_str); -    json_object_string_add(json_row, "rp", rp_str); -    json_object_string_add(json_row, "local", local_str); -    json_object_string_add(json_row, "sptSetup", spt_str); -    json_object_string_add(json_row, "upTime", timebuf); -    json_object_string_add(json_row, "stateTimer", statetimer); -    json_object_object_add(json_group, src_str, json_row); -  } else { -    vty_out (vty, "SA : %s\n", sa->sg_str); -    vty_out (vty, "  RP          : %s\n", rp_str); -    vty_out (vty, "  Peer        : %s\n", peer_str); -    vty_out (vty, "  Local       : %s\n", local_str); -    vty_out (vty, "  SPT Setup   : %s\n", spt_str); -    vty_out (vty, "  Uptime      : %s\n", timebuf); -    vty_out (vty, "  State Timer : %s\n", statetimer); -    vty_out (vty, "\n"); -  } -} - -static void -ip_msdp_show_sa_detail(struct vty *vty, u_char uj) -{ -  struct listnode *sanode; -  struct pim_msdp_sa *sa; -  char src_str[INET_ADDRSTRLEN]; -  char grp_str[INET_ADDRSTRLEN]; -  json_object *json = NULL; - -  if (uj) { -    json = json_object_new_object(); -  } - -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); -    ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); -  } - -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	u_char uj = use_json(argc, argv); +	if (uj) +		argc--; + +	if (argc > 4) +		ip_msdp_show_peers_detail(vty, argv[4]->arg, uj); +	else +		ip_msdp_show_peers(vty, uj); + +	return CMD_SUCCESS; +} + +static void ip_msdp_show_sa(struct vty *vty, u_char uj) +{ +	struct listnode *sanode; +	struct pim_msdp_sa *sa; +	char src_str[INET_ADDRSTRLEN]; +	char grp_str[INET_ADDRSTRLEN]; +	char rp_str[INET_ADDRSTRLEN]; +	char timebuf[PIM_MSDP_UPTIME_STRLEN]; +	char spt_str[8]; +	char local_str[8]; +	int64_t now; +	json_object *json = NULL; +	json_object *json_group = NULL; +	json_object *json_row = NULL; + +	if (uj) { +		json = json_object_new_object(); +	} else { +		vty_out(vty, +			"Source                     Group               RP  Local  SPT    Uptime\n"); +	} + +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		now = pim_time_monotonic_sec(); +		pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); +		pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); +		if (sa->flags & PIM_MSDP_SAF_PEER) { +			pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); +			if (sa->up) { +				strcpy(spt_str, "yes"); +			} else { +				strcpy(spt_str, "no"); +			} +		} else { +			strcpy(rp_str, "-"); +			strcpy(spt_str, "-"); +		} +		if (sa->flags & PIM_MSDP_SAF_LOCAL) { +			strcpy(local_str, "yes"); +		} else { +			strcpy(local_str, "no"); +		} +		if (uj) { +			json_object_object_get_ex(json, grp_str, &json_group); + +			if (!json_group) { +				json_group = json_object_new_object(); +				json_object_object_add(json, grp_str, +						       json_group); +			} + +			json_row = json_object_new_object(); +			json_object_string_add(json_row, "source", src_str); +			json_object_string_add(json_row, "group", grp_str); +			json_object_string_add(json_row, "rp", rp_str); +			json_object_string_add(json_row, "local", local_str); +			json_object_string_add(json_row, "sptSetup", spt_str); +			json_object_string_add(json_row, "upTime", timebuf); +			json_object_object_add(json_group, src_str, json_row); +		} else { +			vty_out(vty, "%-15s  %15s  %15s  %5c  %3c  %8s\n", +				src_str, grp_str, rp_str, local_str[0], +				spt_str[0], timebuf); +		} +	} + + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	} +} + +static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, +					 const char *src_str, +					 const char *grp_str, struct vty *vty, +					 u_char uj, json_object *json) +{ +	char rp_str[INET_ADDRSTRLEN]; +	char peer_str[INET_ADDRSTRLEN]; +	char timebuf[PIM_MSDP_UPTIME_STRLEN]; +	char spt_str[8]; +	char local_str[8]; +	char statetimer[PIM_MSDP_TIMER_STRLEN]; +	int64_t now; +	json_object *json_group = NULL; +	json_object *json_row = NULL; + +	now = pim_time_monotonic_sec(); +	pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); +	if (sa->flags & PIM_MSDP_SAF_PEER) { +		pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); +		pim_inet4_dump("<peer?>", sa->peer, peer_str, sizeof(peer_str)); +		if (sa->up) { +			strcpy(spt_str, "yes"); +		} else { +			strcpy(spt_str, "no"); +		} +	} else { +		strcpy(rp_str, "-"); +		strcpy(peer_str, "-"); +		strcpy(spt_str, "-"); +	} +	if (sa->flags & PIM_MSDP_SAF_LOCAL) { +		strcpy(local_str, "yes"); +	} else { +		strcpy(local_str, "no"); +	} +	pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), +				 sa->sa_state_timer); +	if (uj) { +		json_object_object_get_ex(json, grp_str, &json_group); + +		if (!json_group) { +			json_group = json_object_new_object(); +			json_object_object_add(json, grp_str, json_group); +		} + +		json_row = json_object_new_object(); +		json_object_string_add(json_row, "source", src_str); +		json_object_string_add(json_row, "group", grp_str); +		json_object_string_add(json_row, "rp", rp_str); +		json_object_string_add(json_row, "local", local_str); +		json_object_string_add(json_row, "sptSetup", spt_str); +		json_object_string_add(json_row, "upTime", timebuf); +		json_object_string_add(json_row, "stateTimer", statetimer); +		json_object_object_add(json_group, src_str, json_row); +	} else { +		vty_out(vty, "SA : %s\n", sa->sg_str); +		vty_out(vty, "  RP          : %s\n", rp_str); +		vty_out(vty, "  Peer        : %s\n", peer_str); +		vty_out(vty, "  Local       : %s\n", local_str); +		vty_out(vty, "  SPT Setup   : %s\n", spt_str); +		vty_out(vty, "  Uptime      : %s\n", timebuf); +		vty_out(vty, "  State Timer : %s\n", statetimer); +		vty_out(vty, "\n"); +	} +} + +static void ip_msdp_show_sa_detail(struct vty *vty, u_char uj) +{ +	struct listnode *sanode; +	struct pim_msdp_sa *sa; +	char src_str[INET_ADDRSTRLEN]; +	char grp_str[INET_ADDRSTRLEN]; +	json_object *json = NULL; + +	if (uj) { +		json = json_object_new_object(); +	} + +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); +		ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, +					     json); +	} + +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  DEFUN (show_ip_msdp_sa_detail, @@ -6721,66 +7169,67 @@ DEFUN (show_ip_msdp_sa_detail,         "Detailed output\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); -  ip_msdp_show_sa_detail(vty, uj); +	u_char uj = use_json(argc, argv); +	ip_msdp_show_sa_detail(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  } -static void -ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj) +static void ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj)  { -  struct listnode *sanode; -  struct pim_msdp_sa *sa; -  char src_str[INET_ADDRSTRLEN]; -  char grp_str[INET_ADDRSTRLEN]; -  json_object *json = NULL; +	struct listnode *sanode; +	struct pim_msdp_sa *sa; +	char src_str[INET_ADDRSTRLEN]; +	char grp_str[INET_ADDRSTRLEN]; +	json_object *json = NULL; -  if (uj) { -    json = json_object_new_object(); -  } +	if (uj) { +		json = json_object_new_object(); +	} -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); -    if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { -      ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); -    } -  } +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); +		if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { +			ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, +						     uj, json); +		} +	} -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  } -static void -ip_msdp_show_sa_sg(struct vty *vty, const char *src, const char *grp, u_char uj) +static void ip_msdp_show_sa_sg(struct vty *vty, const char *src, +			       const char *grp, u_char uj)  { -  struct listnode *sanode; -  struct pim_msdp_sa *sa; -  char src_str[INET_ADDRSTRLEN]; -  char grp_str[INET_ADDRSTRLEN]; -  json_object *json = NULL; +	struct listnode *sanode; +	struct pim_msdp_sa *sa; +	char src_str[INET_ADDRSTRLEN]; +	char grp_str[INET_ADDRSTRLEN]; +	json_object *json = NULL; -  if (uj) { -    json = json_object_new_object(); -  } +	if (uj) { +		json = json_object_new_object(); +	} -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); -    if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { -      ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); -    } -  } +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); +		if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { +			ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, +						     uj, json); +		} +	} -  if (uj) { -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	if (uj) { +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  }  DEFUN (show_ip_msdp_sa_sg, @@ -6794,218 +7243,227 @@ DEFUN (show_ip_msdp_sa_sg,         "group ip\n"         "JavaScript Object Notation\n")  { -  u_char uj = use_json(argc, argv); +	u_char uj = use_json(argc, argv); -  int idx = 0; -  char *src_ip = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg : NULL; -  char *grp_ip = idx < argc && argv_find (argv, argc, "A.B.C.D", &idx) ? -                 argv[idx]->arg : NULL; +	int idx = 0; +	char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg +							      : NULL; +	char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) +			       ? argv[idx]->arg +			       : NULL; -  if (src_ip && grp_ip) -    ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj); -  else if (src_ip) -    ip_msdp_show_sa_addr(vty, src_ip, uj); -  else -    ip_msdp_show_sa(vty, uj); +	if (src_ip && grp_ip) +		ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj); +	else if (src_ip) +		ip_msdp_show_sa_addr(vty, src_ip, uj); +	else +		ip_msdp_show_sa(vty, uj); -  return CMD_SUCCESS; +	return CMD_SUCCESS;  }  void pim_cmd_init()  { -  install_node (&pim_global_node, pim_global_config_write);       /* PIM_NODE */ -  install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */ -  if_cmd_init (); - -  install_node (&debug_node, pim_debug_config_write); - -  install_element (CONFIG_NODE, &ip_multicast_routing_cmd); -  install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd); -  install_element (CONFIG_NODE, &ip_pim_rp_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_rp_cmd); -  install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd); -  install_element (CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd); -  install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd); -  install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd); -  install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd); -  install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); -  install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); -  install_element (CONFIG_NODE, &ip_pim_packets_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_packets_cmd); -  install_element (CONFIG_NODE, &ip_pim_v6_secondary_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_cmd); -  install_element (CONFIG_NODE, &ip_ssmpingd_cmd); -  install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd);  -  install_element (CONFIG_NODE, &ip_msdp_peer_cmd); -  install_element (CONFIG_NODE, &no_ip_msdp_peer_cmd); -  install_element (CONFIG_NODE, &ip_pim_ecmp_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_ecmp_cmd); -  install_element (CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd); -  install_element (CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); - -  install_element (INTERFACE_NODE, &interface_ip_igmp_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd);  -  install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);  -  install_element (INTERFACE_NODE, &interface_ip_igmp_version_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_igmp_version_cmd); -  install_element (INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd);  -  install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_cmd);  -  install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_dsec_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_dsec_cmd);  -  install_element (INTERFACE_NODE, &interface_ip_pim_ssm_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd); -  install_element (INTERFACE_NODE, &interface_ip_pim_sm_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_pim_sm_cmd); -  install_element (INTERFACE_NODE, &interface_ip_pim_drprio_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd); -  install_element (INTERFACE_NODE, &interface_ip_pim_hello_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_pim_hello_cmd); - -  // Static mroutes NEB -  install_element (INTERFACE_NODE, &interface_ip_mroute_cmd); -  install_element (INTERFACE_NODE, &interface_ip_mroute_source_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_mroute_cmd); -  install_element (INTERFACE_NODE, &interface_no_ip_mroute_source_cmd); - -  install_element (VIEW_NODE, &show_ip_igmp_interface_cmd); -  install_element (VIEW_NODE, &show_ip_igmp_join_cmd); -  install_element (VIEW_NODE, &show_ip_igmp_groups_cmd); -  install_element (VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd); -  install_element (VIEW_NODE, &show_ip_igmp_sources_cmd); -  install_element (VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd); -  install_element (VIEW_NODE, &show_ip_pim_assert_cmd); -  install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd); -  install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd); -  install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); -  install_element (VIEW_NODE, &show_ip_pim_interface_traffic_cmd); -  install_element (VIEW_NODE, &show_ip_pim_interface_cmd); -  install_element (VIEW_NODE, &show_ip_pim_join_cmd); -  install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd); -  install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd); -  install_element (VIEW_NODE, &show_ip_pim_rpf_cmd); -  install_element (VIEW_NODE, &show_ip_pim_secondary_cmd); -  install_element (VIEW_NODE, &show_ip_pim_state_cmd); -  install_element (VIEW_NODE, &show_ip_pim_upstream_cmd); -  install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); -  install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); -  install_element (VIEW_NODE, &show_ip_pim_rp_cmd); -  install_element (VIEW_NODE, &show_ip_multicast_cmd); -  install_element (VIEW_NODE, &show_ip_mroute_cmd); -  install_element (VIEW_NODE, &show_ip_mroute_count_cmd); -  install_element (VIEW_NODE, &show_ip_rib_cmd); -  install_element (VIEW_NODE, &show_ip_ssmpingd_cmd); -  install_element (VIEW_NODE, &show_debugging_pim_cmd); -  install_element (VIEW_NODE, &show_ip_pim_nexthop_cmd); -  install_element (VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); - -  install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); -  install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); -  install_element (ENABLE_NODE, &clear_ip_mroute_cmd); -  install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd); -  install_element (ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); -  install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd); - -  install_element (ENABLE_NODE, &debug_igmp_cmd); -  install_element (ENABLE_NODE, &no_debug_igmp_cmd); -  install_element (ENABLE_NODE, &debug_igmp_events_cmd); -  install_element (ENABLE_NODE, &no_debug_igmp_events_cmd); -  install_element (ENABLE_NODE, &debug_igmp_packets_cmd); -  install_element (ENABLE_NODE, &no_debug_igmp_packets_cmd); -  install_element (ENABLE_NODE, &debug_igmp_trace_cmd); -  install_element (ENABLE_NODE, &no_debug_igmp_trace_cmd); -  install_element (ENABLE_NODE, &debug_mroute_cmd); -  install_element (ENABLE_NODE, &debug_mroute_detail_cmd); -  install_element (ENABLE_NODE, &no_debug_mroute_cmd); -  install_element (ENABLE_NODE, &no_debug_mroute_detail_cmd); -  install_element (ENABLE_NODE, &debug_static_cmd); -  install_element (ENABLE_NODE, &no_debug_static_cmd); -  install_element (ENABLE_NODE, &debug_pim_cmd); -  install_element (ENABLE_NODE, &no_debug_pim_cmd); -  install_element (ENABLE_NODE, &debug_pim_events_cmd); -  install_element (ENABLE_NODE, &no_debug_pim_events_cmd); -  install_element (ENABLE_NODE, &debug_pim_packets_cmd); -  install_element (ENABLE_NODE, &no_debug_pim_packets_cmd); -  install_element (ENABLE_NODE, &debug_pim_packetdump_send_cmd); -  install_element (ENABLE_NODE, &no_debug_pim_packetdump_send_cmd); -  install_element (ENABLE_NODE, &debug_pim_packetdump_recv_cmd); -  install_element (ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd); -  install_element (ENABLE_NODE, &debug_pim_trace_cmd); -  install_element (ENABLE_NODE, &no_debug_pim_trace_cmd); -  install_element (ENABLE_NODE, &debug_ssmpingd_cmd); -  install_element (ENABLE_NODE, &no_debug_ssmpingd_cmd); -  install_element (ENABLE_NODE, &debug_pim_zebra_cmd); -  install_element (ENABLE_NODE, &no_debug_pim_zebra_cmd); -  install_element (ENABLE_NODE, &debug_msdp_cmd); -  install_element (ENABLE_NODE, &no_debug_msdp_cmd); -  install_element (ENABLE_NODE, &undebug_msdp_cmd); -  install_element (ENABLE_NODE, &debug_msdp_events_cmd); -  install_element (ENABLE_NODE, &no_debug_msdp_events_cmd); -  install_element (ENABLE_NODE, &undebug_msdp_events_cmd); -  install_element (ENABLE_NODE, &debug_msdp_packets_cmd); -  install_element (ENABLE_NODE, &no_debug_msdp_packets_cmd); -  install_element (ENABLE_NODE, &undebug_msdp_packets_cmd); - -  install_element (CONFIG_NODE, &debug_igmp_cmd); -  install_element (CONFIG_NODE, &no_debug_igmp_cmd); -  install_element (CONFIG_NODE, &debug_igmp_events_cmd); -  install_element (CONFIG_NODE, &no_debug_igmp_events_cmd); -  install_element (CONFIG_NODE, &debug_igmp_packets_cmd); -  install_element (CONFIG_NODE, &no_debug_igmp_packets_cmd); -  install_element (CONFIG_NODE, &debug_igmp_trace_cmd); -  install_element (CONFIG_NODE, &no_debug_igmp_trace_cmd); -  install_element (CONFIG_NODE, &debug_mroute_cmd); -  install_element (CONFIG_NODE, &debug_mroute_detail_cmd); -  install_element (CONFIG_NODE, &no_debug_mroute_cmd); -  install_element (CONFIG_NODE, &no_debug_mroute_detail_cmd); -  install_element (CONFIG_NODE, &debug_static_cmd); -  install_element (CONFIG_NODE, &no_debug_static_cmd); -  install_element (CONFIG_NODE, &debug_pim_cmd); -  install_element (CONFIG_NODE, &no_debug_pim_cmd); -  install_element (CONFIG_NODE, &debug_pim_events_cmd); -  install_element (CONFIG_NODE, &no_debug_pim_events_cmd); -  install_element (CONFIG_NODE, &debug_pim_packets_cmd); -  install_element (CONFIG_NODE, &no_debug_pim_packets_cmd); -  install_element (CONFIG_NODE, &debug_pim_trace_cmd); -  install_element (CONFIG_NODE, &no_debug_pim_trace_cmd); -  install_element (CONFIG_NODE, &debug_ssmpingd_cmd); -  install_element (CONFIG_NODE, &no_debug_ssmpingd_cmd); -  install_element (CONFIG_NODE, &debug_pim_zebra_cmd); -  install_element (CONFIG_NODE, &no_debug_pim_zebra_cmd); -  install_element (CONFIG_NODE, &debug_msdp_cmd); -  install_element (CONFIG_NODE, &no_debug_msdp_cmd); -  install_element (CONFIG_NODE, &undebug_msdp_cmd); -  install_element (CONFIG_NODE, &debug_msdp_events_cmd); -  install_element (CONFIG_NODE, &no_debug_msdp_events_cmd); -  install_element (CONFIG_NODE, &undebug_msdp_events_cmd); -  install_element (CONFIG_NODE, &debug_msdp_packets_cmd); -  install_element (CONFIG_NODE, &no_debug_msdp_packets_cmd); -  install_element (CONFIG_NODE, &undebug_msdp_packets_cmd); -  install_element (CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); -  install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); -  install_element (CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); -  install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); -  install_element (VIEW_NODE, &show_ip_msdp_peer_detail_cmd); -  install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd); -  install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd); -  install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd); -  install_element (VIEW_NODE, &show_ip_pim_ssm_range_cmd); -  install_element (VIEW_NODE, &show_ip_pim_group_type_cmd); -  install_element (INTERFACE_NODE, &interface_pim_use_source_cmd); -  install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd); -  /* Install BFD command */ -  install_element (INTERFACE_NODE, &ip_pim_bfd_cmd); -  install_element (INTERFACE_NODE, &ip_pim_bfd_param_cmd); -  install_element (INTERFACE_NODE, &no_ip_pim_bfd_cmd); -  install_element (INTERFACE_NODE, &no_ip_pim_bfd_param_cmd); +	install_node(&pim_global_node, pim_global_config_write); /* PIM_NODE */ +	install_node(&interface_node, +		     pim_interface_config_write); /* INTERFACE_NODE */ +	if_cmd_init(); + +	install_node(&debug_node, pim_debug_config_write); + +	install_element(CONFIG_NODE, &ip_multicast_routing_cmd); +	install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd); +	install_element(CONFIG_NODE, &ip_pim_rp_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_rp_cmd); +	install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd); +	install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd); +	install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd); +	install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd); +	install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd); +	install_element(CONFIG_NODE, +			&no_ip_pim_spt_switchover_infinity_plist_cmd); +	install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); +	install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd); +	install_element(CONFIG_NODE, &ip_pim_packets_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_packets_cmd); +	install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd); +	install_element(CONFIG_NODE, &ip_ssmpingd_cmd); +	install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd); +	install_element(CONFIG_NODE, &ip_msdp_peer_cmd); +	install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd); +	install_element(CONFIG_NODE, &ip_pim_ecmp_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd); +	install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd); +	install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); + +	install_element(INTERFACE_NODE, &interface_ip_igmp_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd); +	install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd); +	install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd); +	install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd); +	install_element(INTERFACE_NODE, +			&interface_no_ip_igmp_query_interval_cmd); +	install_element(INTERFACE_NODE, +			&interface_ip_igmp_query_max_response_time_cmd); +	install_element(INTERFACE_NODE, +			&interface_no_ip_igmp_query_max_response_time_cmd); +	install_element(INTERFACE_NODE, +			&interface_ip_igmp_query_max_response_time_dsec_cmd); +	install_element(INTERFACE_NODE, +			&interface_no_ip_igmp_query_max_response_time_dsec_cmd); +	install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd); +	install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd); +	install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd); +	install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd); + +	// Static mroutes NEB +	install_element(INTERFACE_NODE, &interface_ip_mroute_cmd); +	install_element(INTERFACE_NODE, &interface_ip_mroute_source_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd); +	install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd); + +	install_element(VIEW_NODE, &show_ip_igmp_interface_cmd); +	install_element(VIEW_NODE, &show_ip_igmp_join_cmd); +	install_element(VIEW_NODE, &show_ip_igmp_groups_cmd); +	install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd); +	install_element(VIEW_NODE, &show_ip_igmp_sources_cmd); +	install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd); +	install_element(VIEW_NODE, &show_ip_pim_assert_cmd); +	install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd); +	install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd); +	install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); +	install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd); +	install_element(VIEW_NODE, &show_ip_pim_interface_cmd); +	install_element(VIEW_NODE, &show_ip_pim_join_cmd); +	install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd); +	install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd); +	install_element(VIEW_NODE, &show_ip_pim_rpf_cmd); +	install_element(VIEW_NODE, &show_ip_pim_secondary_cmd); +	install_element(VIEW_NODE, &show_ip_pim_state_cmd); +	install_element(VIEW_NODE, &show_ip_pim_upstream_cmd); +	install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); +	install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); +	install_element(VIEW_NODE, &show_ip_pim_rp_cmd); +	install_element(VIEW_NODE, &show_ip_multicast_cmd); +	install_element(VIEW_NODE, &show_ip_mroute_cmd); +	install_element(VIEW_NODE, &show_ip_mroute_count_cmd); +	install_element(VIEW_NODE, &show_ip_rib_cmd); +	install_element(VIEW_NODE, &show_ip_ssmpingd_cmd); +	install_element(VIEW_NODE, &show_debugging_pim_cmd); +	install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd); +	install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); + +	install_element(ENABLE_NODE, &clear_ip_interfaces_cmd); +	install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); +	install_element(ENABLE_NODE, &clear_ip_mroute_cmd); +	install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd); +	install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); +	install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd); + +	install_element(ENABLE_NODE, &debug_igmp_cmd); +	install_element(ENABLE_NODE, &no_debug_igmp_cmd); +	install_element(ENABLE_NODE, &debug_igmp_events_cmd); +	install_element(ENABLE_NODE, &no_debug_igmp_events_cmd); +	install_element(ENABLE_NODE, &debug_igmp_packets_cmd); +	install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd); +	install_element(ENABLE_NODE, &debug_igmp_trace_cmd); +	install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd); +	install_element(ENABLE_NODE, &debug_mroute_cmd); +	install_element(ENABLE_NODE, &debug_mroute_detail_cmd); +	install_element(ENABLE_NODE, &no_debug_mroute_cmd); +	install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd); +	install_element(ENABLE_NODE, &debug_static_cmd); +	install_element(ENABLE_NODE, &no_debug_static_cmd); +	install_element(ENABLE_NODE, &debug_pim_cmd); +	install_element(ENABLE_NODE, &no_debug_pim_cmd); +	install_element(ENABLE_NODE, &debug_pim_events_cmd); +	install_element(ENABLE_NODE, &no_debug_pim_events_cmd); +	install_element(ENABLE_NODE, &debug_pim_packets_cmd); +	install_element(ENABLE_NODE, &no_debug_pim_packets_cmd); +	install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd); +	install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd); +	install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd); +	install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd); +	install_element(ENABLE_NODE, &debug_pim_trace_cmd); +	install_element(ENABLE_NODE, &no_debug_pim_trace_cmd); +	install_element(ENABLE_NODE, &debug_ssmpingd_cmd); +	install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd); +	install_element(ENABLE_NODE, &debug_pim_zebra_cmd); +	install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd); +	install_element(ENABLE_NODE, &debug_msdp_cmd); +	install_element(ENABLE_NODE, &no_debug_msdp_cmd); +	install_element(ENABLE_NODE, &undebug_msdp_cmd); +	install_element(ENABLE_NODE, &debug_msdp_events_cmd); +	install_element(ENABLE_NODE, &no_debug_msdp_events_cmd); +	install_element(ENABLE_NODE, &undebug_msdp_events_cmd); +	install_element(ENABLE_NODE, &debug_msdp_packets_cmd); +	install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd); +	install_element(ENABLE_NODE, &undebug_msdp_packets_cmd); + +	install_element(CONFIG_NODE, &debug_igmp_cmd); +	install_element(CONFIG_NODE, &no_debug_igmp_cmd); +	install_element(CONFIG_NODE, &debug_igmp_events_cmd); +	install_element(CONFIG_NODE, &no_debug_igmp_events_cmd); +	install_element(CONFIG_NODE, &debug_igmp_packets_cmd); +	install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd); +	install_element(CONFIG_NODE, &debug_igmp_trace_cmd); +	install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd); +	install_element(CONFIG_NODE, &debug_mroute_cmd); +	install_element(CONFIG_NODE, &debug_mroute_detail_cmd); +	install_element(CONFIG_NODE, &no_debug_mroute_cmd); +	install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd); +	install_element(CONFIG_NODE, &debug_static_cmd); +	install_element(CONFIG_NODE, &no_debug_static_cmd); +	install_element(CONFIG_NODE, &debug_pim_cmd); +	install_element(CONFIG_NODE, &no_debug_pim_cmd); +	install_element(CONFIG_NODE, &debug_pim_events_cmd); +	install_element(CONFIG_NODE, &no_debug_pim_events_cmd); +	install_element(CONFIG_NODE, &debug_pim_packets_cmd); +	install_element(CONFIG_NODE, &no_debug_pim_packets_cmd); +	install_element(CONFIG_NODE, &debug_pim_trace_cmd); +	install_element(CONFIG_NODE, &no_debug_pim_trace_cmd); +	install_element(CONFIG_NODE, &debug_ssmpingd_cmd); +	install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd); +	install_element(CONFIG_NODE, &debug_pim_zebra_cmd); +	install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd); +	install_element(CONFIG_NODE, &debug_msdp_cmd); +	install_element(CONFIG_NODE, &no_debug_msdp_cmd); +	install_element(CONFIG_NODE, &undebug_msdp_cmd); +	install_element(CONFIG_NODE, &debug_msdp_events_cmd); +	install_element(CONFIG_NODE, &no_debug_msdp_events_cmd); +	install_element(CONFIG_NODE, &undebug_msdp_events_cmd); +	install_element(CONFIG_NODE, &debug_msdp_packets_cmd); +	install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd); +	install_element(CONFIG_NODE, &undebug_msdp_packets_cmd); +	install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); +	install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); +	install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); +	install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); +	install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd); +	install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd); +	install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd); +	install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd); +	install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd); +	install_element(VIEW_NODE, &show_ip_pim_group_type_cmd); +	install_element(INTERFACE_NODE, &interface_pim_use_source_cmd); +	install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd); +	/* Install BFD command */ +	install_element(INTERFACE_NODE, &ip_pim_bfd_cmd); +	install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd); +	install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd); +	install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);  } diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 0c08cfa46d..2592514f38 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -32,71 +32,66 @@  #include "pim_neighbor.h"  #include "pim_upstream.h" -static void on_trace(const char *label, -		     struct interface *ifp, struct in_addr src) +static void on_trace(const char *label, struct interface *ifp, +		     struct in_addr src)  { -  if (PIM_DEBUG_PIM_TRACE) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); -    zlog_debug("%s: from %s on %s", -	       label, src_str, ifp->name); -  } +	if (PIM_DEBUG_PIM_TRACE) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); +		zlog_debug("%s: from %s on %s", label, src_str, ifp->name); +	}  }  static void tlv_trace_bool(const char *label, const char *tlv_name,  			   const char *ifname, struct in_addr src_addr,  			   int isset, int value)  { -  if (isset) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_debug("%s: PIM hello option from %s on interface %s: %s=%d", -	       label,  -	       src_str, ifname, -	       tlv_name, value); -  } +	if (isset) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_debug( +			"%s: PIM hello option from %s on interface %s: %s=%d", +			label, src_str, ifname, tlv_name, value); +	}  }  static void tlv_trace_uint16(const char *label, const char *tlv_name,  			     const char *ifname, struct in_addr src_addr,  			     int isset, uint16_t value)  { -  if (isset) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", -	       label,  -	       src_str, ifname, -	       tlv_name, value); -  } +	if (isset) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_debug( +			"%s: PIM hello option from %s on interface %s: %s=%u", +			label, src_str, ifname, tlv_name, value); +	}  }  static void tlv_trace_uint32(const char *label, const char *tlv_name,  			     const char *ifname, struct in_addr src_addr,  			     int isset, uint32_t value)  { -  if (isset) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", -	       label,  -	       src_str, ifname, -	       tlv_name, value); -  } +	if (isset) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_debug( +			"%s: PIM hello option from %s on interface %s: %s=%u", +			label, src_str, ifname, tlv_name, value); +	}  }  static void tlv_trace_uint32_hex(const char *label, const char *tlv_name,  				 const char *ifname, struct in_addr src_addr,  				 int isset, uint32_t value)  { -  if (isset) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_debug("%s: PIM hello option from %s on interface %s: %s=%08x", -	       label,  -	       src_str, ifname, -	       tlv_name, value); -  } +	if (isset) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_debug( +			"%s: PIM hello option from %s on interface %s: %s=%08x", +			label, src_str, ifname, tlv_name, value); +	}  }  #if 0 @@ -119,418 +114,423 @@ static void tlv_trace_list(const char *label, const char *tlv_name,  			   const char *ifname, struct in_addr src_addr,  			   int isset, struct list *addr_list)  { -  if (isset) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_debug("%s: PIM hello option from %s on interface %s: %s size=%d list=%p", -	       label,  -	       src_str, ifname, -	       tlv_name, -	       addr_list ? ((int) listcount(addr_list)) : -1, -	       (void *) addr_list); -  } +	if (isset) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_debug( +			"%s: PIM hello option from %s on interface %s: %s size=%d list=%p", +			label, src_str, ifname, tlv_name, +			addr_list ? ((int)listcount(addr_list)) : -1, +			(void *)addr_list); +	}  } -#define FREE_ADDR_LIST \ -  if (hello_option_addr_list) { \ -    list_delete(hello_option_addr_list); \ -  } +#define FREE_ADDR_LIST                                                         \ +	if (hello_option_addr_list) {                                          \ +		list_delete(hello_option_addr_list);                           \ +	} -#define FREE_ADDR_LIST_THEN_RETURN(code) \ -{ \ -  FREE_ADDR_LIST \ -  return (code); \ -} +#define FREE_ADDR_LIST_THEN_RETURN(code)                                       \ +	{                                                                      \ +		FREE_ADDR_LIST                                                 \ +		return (code);                                                 \ +	} -int pim_hello_recv(struct interface *ifp, -		   struct in_addr src_addr, +int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,  		   uint8_t *tlv_buf, int tlv_buf_size)  { -  struct pim_interface *pim_ifp; -  struct pim_neighbor *neigh; -  uint8_t *tlv_curr; -  uint8_t *tlv_pastend; -  pim_hello_options hello_options = 0; /* bit array recording options found */ -  uint16_t hello_option_holdtime = 0; -  uint16_t hello_option_propagation_delay = 0; -  uint16_t hello_option_override_interval = 0; -  uint32_t hello_option_dr_priority = 0; -  uint32_t hello_option_generation_id = 0; -  struct list *hello_option_addr_list = 0; - -  if (PIM_DEBUG_PIM_HELLO) -    on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  ++pim_ifp->pim_ifstat_hello_recv; - -  /* -    Parse PIM hello TLVs -   */ -  zassert(tlv_buf_size >= 0); -  tlv_curr = tlv_buf; -  tlv_pastend = tlv_buf + tlv_buf_size; - -  while (tlv_curr < tlv_pastend) { -    uint16_t option_type;  -    uint16_t option_len; -    int remain = tlv_pastend - tlv_curr; - -    if (remain < PIM_TLV_MIN_SIZE) { -      if (PIM_DEBUG_PIM_HELLO) { -	char src_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	zlog_debug("%s: short PIM hello TLV size=%d < min=%d from %s on interface %s", -		   __PRETTY_FUNCTION__, -		   remain, PIM_TLV_MIN_SIZE, -		   src_str, ifp->name); -      } -      FREE_ADDR_LIST_THEN_RETURN(-1); -    } - -    option_type = PIM_TLV_GET_TYPE(tlv_curr); -    tlv_curr += PIM_TLV_TYPE_SIZE; -    option_len = PIM_TLV_GET_LENGTH(tlv_curr); -    tlv_curr += PIM_TLV_LENGTH_SIZE; - -    if ((tlv_curr + option_len) > tlv_pastend) { -      if (PIM_DEBUG_PIM_HELLO) { -	char src_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	zlog_debug("%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s", -		   __PRETTY_FUNCTION__, -		   option_type, option_len, tlv_pastend - tlv_curr, -		   src_str, ifp->name); -      } -      FREE_ADDR_LIST_THEN_RETURN(-2); -    } - -    if (PIM_DEBUG_PIM_HELLO) { -      char src_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -      zlog_debug("%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s", -		 __PRETTY_FUNCTION__, -		 remain, -		 option_type, option_len, -		 src_str, ifp->name); -    } - -    switch (option_type) { -    case PIM_MSG_OPTION_TYPE_HOLDTIME: -      if (pim_tlv_parse_holdtime(ifp->name, src_addr, -				 &hello_options, -				 &hello_option_holdtime, -				 option_len, -				 tlv_curr)) { -	FREE_ADDR_LIST_THEN_RETURN(-3); -      } -      break; -    case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY: -      if (pim_tlv_parse_lan_prune_delay(ifp->name, src_addr, -					&hello_options, -					&hello_option_propagation_delay, -					&hello_option_override_interval, -					option_len, -					tlv_curr)) { -	FREE_ADDR_LIST_THEN_RETURN(-4); -      } -      break; -    case PIM_MSG_OPTION_TYPE_DR_PRIORITY: -      if (pim_tlv_parse_dr_priority(ifp->name, src_addr, -				    &hello_options, -				    &hello_option_dr_priority, -				    option_len, +	struct pim_interface *pim_ifp; +	struct pim_neighbor *neigh; +	uint8_t *tlv_curr; +	uint8_t *tlv_pastend; +	pim_hello_options hello_options = +		0; /* bit array recording options found */ +	uint16_t hello_option_holdtime = 0; +	uint16_t hello_option_propagation_delay = 0; +	uint16_t hello_option_override_interval = 0; +	uint32_t hello_option_dr_priority = 0; +	uint32_t hello_option_generation_id = 0; +	struct list *hello_option_addr_list = 0; + +	if (PIM_DEBUG_PIM_HELLO) +		on_trace(__PRETTY_FUNCTION__, ifp, src_addr); + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	++pim_ifp->pim_ifstat_hello_recv; + +	/* +	  Parse PIM hello TLVs +	 */ +	zassert(tlv_buf_size >= 0); +	tlv_curr = tlv_buf; +	tlv_pastend = tlv_buf + tlv_buf_size; + +	while (tlv_curr < tlv_pastend) { +		uint16_t option_type; +		uint16_t option_len; +		int remain = tlv_pastend - tlv_curr; + +		if (remain < PIM_TLV_MIN_SIZE) { +			if (PIM_DEBUG_PIM_HELLO) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_debug( +					"%s: short PIM hello TLV size=%d < min=%d from %s on interface %s", +					__PRETTY_FUNCTION__, remain, +					PIM_TLV_MIN_SIZE, src_str, ifp->name); +			} +			FREE_ADDR_LIST_THEN_RETURN(-1); +		} + +		option_type = PIM_TLV_GET_TYPE(tlv_curr); +		tlv_curr += PIM_TLV_TYPE_SIZE; +		option_len = PIM_TLV_GET_LENGTH(tlv_curr); +		tlv_curr += PIM_TLV_LENGTH_SIZE; + +		if ((tlv_curr + option_len) > tlv_pastend) { +			if (PIM_DEBUG_PIM_HELLO) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_debug( +					"%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s", +					__PRETTY_FUNCTION__, option_type, +					option_len, tlv_pastend - tlv_curr, +					src_str, ifp->name); +			} +			FREE_ADDR_LIST_THEN_RETURN(-2); +		} + +		if (PIM_DEBUG_PIM_HELLO) { +			char src_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<src?>", src_addr, src_str, +				       sizeof(src_str)); +			zlog_debug( +				"%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s", +				__PRETTY_FUNCTION__, remain, option_type, +				option_len, src_str, ifp->name); +		} + +		switch (option_type) { +		case PIM_MSG_OPTION_TYPE_HOLDTIME: +			if (pim_tlv_parse_holdtime(ifp->name, src_addr, +						   &hello_options, +						   &hello_option_holdtime, +						   option_len, tlv_curr)) { +				FREE_ADDR_LIST_THEN_RETURN(-3); +			} +			break; +		case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY: +			if (pim_tlv_parse_lan_prune_delay( +				    ifp->name, src_addr, &hello_options, +				    &hello_option_propagation_delay, +				    &hello_option_override_interval, option_len,  				    tlv_curr)) { -	FREE_ADDR_LIST_THEN_RETURN(-5); -      } -      break; -    case PIM_MSG_OPTION_TYPE_GENERATION_ID: -      if (pim_tlv_parse_generation_id(ifp->name, src_addr, -				      &hello_options, -				      &hello_option_generation_id, -				      option_len, -				      tlv_curr)) { -	FREE_ADDR_LIST_THEN_RETURN(-6); -      } -      break; -    case PIM_MSG_OPTION_TYPE_ADDRESS_LIST: -      if (pim_tlv_parse_addr_list(ifp->name, src_addr, -				  &hello_options, -				  &hello_option_addr_list, -				  option_len, -				  tlv_curr)) { -	return -7; -      } -      break; -    case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: -      if (PIM_DEBUG_PIM_HELLO) { -	char src_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	zlog_debug("%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s", -		   __PRETTY_FUNCTION__, -		   option_type, option_len, -		   src_str, ifp->name); -      } -      break; -    default: -      if (PIM_DEBUG_PIM_HELLO) { -	char src_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	zlog_debug("%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s", -		   __PRETTY_FUNCTION__, -		   option_type, option_len, -		   src_str, ifp->name); -      } -    } - -    tlv_curr += option_len; -  } +				FREE_ADDR_LIST_THEN_RETURN(-4); +			} +			break; +		case PIM_MSG_OPTION_TYPE_DR_PRIORITY: +			if (pim_tlv_parse_dr_priority(ifp->name, src_addr, +						      &hello_options, +						      &hello_option_dr_priority, +						      option_len, tlv_curr)) { +				FREE_ADDR_LIST_THEN_RETURN(-5); +			} +			break; +		case PIM_MSG_OPTION_TYPE_GENERATION_ID: +			if (pim_tlv_parse_generation_id( +				    ifp->name, src_addr, &hello_options, +				    &hello_option_generation_id, option_len, +				    tlv_curr)) { +				FREE_ADDR_LIST_THEN_RETURN(-6); +			} +			break; +		case PIM_MSG_OPTION_TYPE_ADDRESS_LIST: +			if (pim_tlv_parse_addr_list(ifp->name, src_addr, +						    &hello_options, +						    &hello_option_addr_list, +						    option_len, tlv_curr)) { +				return -7; +			} +			break; +		case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: +			if (PIM_DEBUG_PIM_HELLO) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_debug( +					"%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s", +					__PRETTY_FUNCTION__, option_type, +					option_len, src_str, ifp->name); +			} +			break; +		default: +			if (PIM_DEBUG_PIM_HELLO) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_debug( +					"%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s", +					__PRETTY_FUNCTION__, option_type, +					option_len, src_str, ifp->name); +			} +		} + +		tlv_curr += option_len; +	} -  /* -    Check received PIM hello options -  */ - -  if (PIM_DEBUG_PIM_HELLO) { -    tlv_trace_uint16(__PRETTY_FUNCTION__, "holdtime", -		     ifp->name, src_addr, -		     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME), -		     hello_option_holdtime); -    tlv_trace_uint16(__PRETTY_FUNCTION__, "propagation_delay", -		     ifp->name, src_addr, -		     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), -		     hello_option_propagation_delay); -    tlv_trace_uint16(__PRETTY_FUNCTION__, "override_interval", -		     ifp->name, src_addr, -		     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), -		     hello_option_override_interval); -    tlv_trace_bool(__PRETTY_FUNCTION__, "can_disable_join_suppression", -		   ifp->name, src_addr, -		   PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), -		   PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)); -    tlv_trace_uint32(__PRETTY_FUNCTION__, "dr_priority", -		     ifp->name, src_addr, -		     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY), -		     hello_option_dr_priority); -    tlv_trace_uint32_hex(__PRETTY_FUNCTION__, "generation_id", -			 ifp->name, src_addr, -			 PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID), -			 hello_option_generation_id); -    tlv_trace_list(__PRETTY_FUNCTION__, "address_list", -		   ifp->name, src_addr, -		   PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_ADDRESS_LIST), -		   hello_option_addr_list); -  } +	/* +	  Check received PIM hello options +	*/ -  if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { -    if (PIM_DEBUG_PIM_HELLO) { -      char src_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -      zlog_debug("%s: PIM hello missing holdtime from %s on interface %s", -		__PRETTY_FUNCTION__, -		src_str, ifp->name); -    } -  } +	if (PIM_DEBUG_PIM_HELLO) { +		tlv_trace_uint16(__PRETTY_FUNCTION__, "holdtime", ifp->name, +				 src_addr, +				 PIM_OPTION_IS_SET(hello_options, +						   PIM_OPTION_MASK_HOLDTIME), +				 hello_option_holdtime); +		tlv_trace_uint16( +			__PRETTY_FUNCTION__, "propagation_delay", ifp->name, +			src_addr, +			PIM_OPTION_IS_SET(hello_options, +					  PIM_OPTION_MASK_LAN_PRUNE_DELAY), +			hello_option_propagation_delay); +		tlv_trace_uint16( +			__PRETTY_FUNCTION__, "override_interval", ifp->name, +			src_addr, +			PIM_OPTION_IS_SET(hello_options, +					  PIM_OPTION_MASK_LAN_PRUNE_DELAY), +			hello_option_override_interval); +		tlv_trace_bool( +			__PRETTY_FUNCTION__, "can_disable_join_suppression", +			ifp->name, src_addr, +			PIM_OPTION_IS_SET(hello_options, +					  PIM_OPTION_MASK_LAN_PRUNE_DELAY), +			PIM_OPTION_IS_SET( +				hello_options, +				PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)); +		tlv_trace_uint32(__PRETTY_FUNCTION__, "dr_priority", ifp->name, +				 src_addr, +				 PIM_OPTION_IS_SET(hello_options, +						   PIM_OPTION_MASK_DR_PRIORITY), +				 hello_option_dr_priority); +		tlv_trace_uint32_hex( +			__PRETTY_FUNCTION__, "generation_id", ifp->name, +			src_addr, +			PIM_OPTION_IS_SET(hello_options, +					  PIM_OPTION_MASK_GENERATION_ID), +			hello_option_generation_id); +		tlv_trace_list(__PRETTY_FUNCTION__, "address_list", ifp->name, +			       src_addr, +			       PIM_OPTION_IS_SET(hello_options, +						 PIM_OPTION_MASK_ADDRESS_LIST), +			       hello_option_addr_list); +	} -  /* -    New neighbor? -  */ - -  neigh = pim_neighbor_find(ifp, src_addr); -  if (!neigh) { -    /* Add as new neighbor */ -     -    neigh = pim_neighbor_add(ifp, src_addr, -			     hello_options, -			     hello_option_holdtime, -			     hello_option_propagation_delay, -			     hello_option_override_interval, -			     hello_option_dr_priority, -			     hello_option_generation_id, -			     hello_option_addr_list, -			     PIM_NEIGHBOR_SEND_DELAY); -    if (!neigh) { -      if (PIM_DEBUG_PIM_HELLO) { -	char src_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	zlog_warn("%s: failure creating PIM neighbor %s on interface %s", -		  __PRETTY_FUNCTION__, -		  src_str, ifp->name); -      } -      FREE_ADDR_LIST_THEN_RETURN(-8); -    } - -    /* actual addr list has been saved under neighbor */ -    return 0; -  } +	if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { +		if (PIM_DEBUG_PIM_HELLO) { +			char src_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<src?>", src_addr, src_str, +				       sizeof(src_str)); +			zlog_debug( +				"%s: PIM hello missing holdtime from %s on interface %s", +				__PRETTY_FUNCTION__, src_str, ifp->name); +		} +	} -  /* -    Received generation ID ? -  */ -   -  if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) { -    /* GenID mismatch ? */ -    if (!PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) || -	(hello_option_generation_id != neigh->generation_id)) { -      /* GenID mismatch, then replace neighbor */ -       -      if (PIM_DEBUG_PIM_HELLO) { -	char src_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	zlog_debug("%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s", -		   __PRETTY_FUNCTION__, -		   hello_option_generation_id, -		   neigh->generation_id, -		   src_str, ifp->name); -      } - -      pim_upstream_rpf_genid_changed(neigh->source_addr); -       -      pim_neighbor_delete(ifp, neigh, "GenID mismatch"); -      neigh = pim_neighbor_add(ifp, src_addr, -			       hello_options, -			       hello_option_holdtime, -			       hello_option_propagation_delay, -			       hello_option_override_interval, -			       hello_option_dr_priority, -			       hello_option_generation_id, -			       hello_option_addr_list, -			       PIM_NEIGHBOR_SEND_NOW); -      if (!neigh) { -	if (PIM_DEBUG_PIM_HELLO) { -	  char src_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	  zlog_debug("%s: failure re-creating PIM neighbor %s on interface %s", -		     __PRETTY_FUNCTION__, -		     src_str, ifp->name); +	/* +	  New neighbor? +	*/ + +	neigh = pim_neighbor_find(ifp, src_addr); +	if (!neigh) { +		/* Add as new neighbor */ + +		neigh = pim_neighbor_add( +			ifp, src_addr, hello_options, hello_option_holdtime, +			hello_option_propagation_delay, +			hello_option_override_interval, +			hello_option_dr_priority, hello_option_generation_id, +			hello_option_addr_list, PIM_NEIGHBOR_SEND_DELAY); +		if (!neigh) { +			if (PIM_DEBUG_PIM_HELLO) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_warn( +					"%s: failure creating PIM neighbor %s on interface %s", +					__PRETTY_FUNCTION__, src_str, +					ifp->name); +			} +			FREE_ADDR_LIST_THEN_RETURN(-8); +		} + +		/* actual addr list has been saved under neighbor */ +		return 0;  	} -	FREE_ADDR_LIST_THEN_RETURN(-9); -      } -      /* actual addr list is saved under neighbor */ -      return 0; - -    } /* GenId mismatch: replace neighbor */ -     -  } /* GenId received */ - -  /* -    Update existing neighbor -  */ - -  pim_neighbor_update(neigh, -		      hello_options, -		      hello_option_holdtime, -		      hello_option_dr_priority, -		      hello_option_addr_list); -  /* actual addr list is saved under neighbor */ -  return 0; + +	/* +	  Received generation ID ? +	*/ + +	if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) { +		/* GenID mismatch ? */ +		if (!PIM_OPTION_IS_SET(neigh->hello_options, +				       PIM_OPTION_MASK_GENERATION_ID) +		    || (hello_option_generation_id != neigh->generation_id)) { +			/* GenID mismatch, then replace neighbor */ + +			if (PIM_DEBUG_PIM_HELLO) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_debug( +					"%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s", +					__PRETTY_FUNCTION__, +					hello_option_generation_id, +					neigh->generation_id, src_str, +					ifp->name); +			} + +			pim_upstream_rpf_genid_changed(neigh->source_addr); + +			pim_neighbor_delete(ifp, neigh, "GenID mismatch"); +			neigh = pim_neighbor_add(ifp, src_addr, hello_options, +						 hello_option_holdtime, +						 hello_option_propagation_delay, +						 hello_option_override_interval, +						 hello_option_dr_priority, +						 hello_option_generation_id, +						 hello_option_addr_list, +						 PIM_NEIGHBOR_SEND_NOW); +			if (!neigh) { +				if (PIM_DEBUG_PIM_HELLO) { +					char src_str[INET_ADDRSTRLEN]; +					pim_inet4_dump("<src?>", src_addr, +						       src_str, +						       sizeof(src_str)); +					zlog_debug( +						"%s: failure re-creating PIM neighbor %s on interface %s", +						__PRETTY_FUNCTION__, src_str, +						ifp->name); +				} +				FREE_ADDR_LIST_THEN_RETURN(-9); +			} +			/* actual addr list is saved under neighbor */ +			return 0; + +		} /* GenId mismatch: replace neighbor */ + +	} /* GenId received */ + +	/* +	  Update existing neighbor +	*/ + +	pim_neighbor_update(neigh, hello_options, hello_option_holdtime, +			    hello_option_dr_priority, hello_option_addr_list); +	/* actual addr list is saved under neighbor */ +	return 0;  } -int pim_hello_build_tlv(struct interface *ifp, -			uint8_t *tlv_buf, int tlv_buf_size, -			uint16_t holdtime, -			uint32_t dr_priority, -			uint32_t generation_id, -			uint16_t propagation_delay, -			uint16_t override_interval, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, +			int tlv_buf_size, uint16_t holdtime, +			uint32_t dr_priority, uint32_t generation_id, +			uint16_t propagation_delay, uint16_t override_interval,  			int can_disable_join_suppression)  { -  uint8_t *curr = tlv_buf; -  uint8_t *pastend = tlv_buf + tlv_buf_size; -  uint8_t *tmp; - -  /* -   * Append options -   */ - -  /* Holdtime */ -  curr = pim_tlv_append_uint16(curr, -			       pastend, -			       PIM_MSG_OPTION_TYPE_HOLDTIME, -			       holdtime); -  if (!curr) { -    if (PIM_DEBUG_PIM_HELLO) { -      zlog_debug("%s: could not set PIM hello Holdtime option for interface %s", -		 __PRETTY_FUNCTION__, ifp->name); -    } -    return -1; -  } +	uint8_t *curr = tlv_buf; +	uint8_t *pastend = tlv_buf + tlv_buf_size; +	uint8_t *tmp; + +	/* +	 * Append options +	 */ + +	/* Holdtime */ +	curr = pim_tlv_append_uint16(curr, pastend, +				     PIM_MSG_OPTION_TYPE_HOLDTIME, holdtime); +	if (!curr) { +		if (PIM_DEBUG_PIM_HELLO) { +			zlog_debug( +				"%s: could not set PIM hello Holdtime option for interface %s", +				__PRETTY_FUNCTION__, ifp->name); +		} +		return -1; +	} -  /* LAN Prune Delay */ -  tmp = pim_tlv_append_2uint16(curr, -			       pastend, -			       PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY, -			       propagation_delay, -			       override_interval); -  if (!tmp) { -    if (PIM_DEBUG_PIM_HELLO) { -      zlog_debug("%s: could not set PIM LAN Prune Delay option for interface %s", -		 __PRETTY_FUNCTION__, ifp->name); -    } -    return -1; -  } -  if (can_disable_join_suppression) { -    *((uint8_t*)(curr) + 4) |= 0x80; /* enable T bit */ -  } -  curr = tmp; - -  /* DR Priority */ -  curr = pim_tlv_append_uint32(curr, -			       pastend, -			       PIM_MSG_OPTION_TYPE_DR_PRIORITY, -			       dr_priority); -  if (!curr) { -    if (PIM_DEBUG_PIM_HELLO) { -      zlog_debug("%s: could not set PIM hello DR Priority option for interface %s", -		 __PRETTY_FUNCTION__, ifp->name); -    } -    return -2; -  } +	/* LAN Prune Delay */ +	tmp = pim_tlv_append_2uint16(curr, pastend, +				     PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY, +				     propagation_delay, override_interval); +	if (!tmp) { +		if (PIM_DEBUG_PIM_HELLO) { +			zlog_debug( +				"%s: could not set PIM LAN Prune Delay option for interface %s", +				__PRETTY_FUNCTION__, ifp->name); +		} +		return -1; +	} +	if (can_disable_join_suppression) { +		*((uint8_t *)(curr) + 4) |= 0x80; /* enable T bit */ +	} +	curr = tmp; + +	/* DR Priority */ +	curr = pim_tlv_append_uint32( +		curr, pastend, PIM_MSG_OPTION_TYPE_DR_PRIORITY, dr_priority); +	if (!curr) { +		if (PIM_DEBUG_PIM_HELLO) { +			zlog_debug( +				"%s: could not set PIM hello DR Priority option for interface %s", +				__PRETTY_FUNCTION__, ifp->name); +		} +		return -2; +	} -  /* Generation ID */ -  curr = pim_tlv_append_uint32(curr, -			       pastend, -			       PIM_MSG_OPTION_TYPE_GENERATION_ID, -			       generation_id); -  if (!curr) { -    if (PIM_DEBUG_PIM_HELLO) { -      zlog_debug("%s: could not set PIM hello Generation ID option for interface %s", -		 __PRETTY_FUNCTION__, ifp->name); -    } -    return -3; -  } +	/* Generation ID */ +	curr = pim_tlv_append_uint32(curr, pastend, +				     PIM_MSG_OPTION_TYPE_GENERATION_ID, +				     generation_id); +	if (!curr) { +		if (PIM_DEBUG_PIM_HELLO) { +			zlog_debug( +				"%s: could not set PIM hello Generation ID option for interface %s", +				__PRETTY_FUNCTION__, ifp->name); +		} +		return -3; +	} -  /* Secondary Address List */ -  if (ifp->connected->count) { -    curr = pim_tlv_append_addrlist_ucast(curr, -					 pastend, -					 ifp->connected, -                                         AF_INET); -    if (!curr) { -      if (PIM_DEBUG_PIM_HELLO) { -	zlog_debug("%s: could not set PIM hello v4 Secondary Address List option for interface %s", -		  __PRETTY_FUNCTION__, ifp->name); -      } -      return -4; -    } -    if (pimg->send_v6_secondary) -      { -        curr = pim_tlv_append_addrlist_ucast(curr, -                                             pastend, -                                             ifp->connected, -                                             AF_INET6); -        if (!curr) { -          if (PIM_DEBUG_PIM_HELLO) { -            zlog_debug("%s: could not sent PIM hello v6 secondary Address List option for interface %s", -                       __PRETTY_FUNCTION__, ifp->name); -          } -          return -4; -        } -      } -  } +	/* Secondary Address List */ +	if (ifp->connected->count) { +		curr = pim_tlv_append_addrlist_ucast(curr, pastend, +						     ifp->connected, AF_INET); +		if (!curr) { +			if (PIM_DEBUG_PIM_HELLO) { +				zlog_debug( +					"%s: could not set PIM hello v4 Secondary Address List option for interface %s", +					__PRETTY_FUNCTION__, ifp->name); +			} +			return -4; +		} +		if (pimg->send_v6_secondary) { +			curr = pim_tlv_append_addrlist_ucast( +				curr, pastend, ifp->connected, AF_INET6); +			if (!curr) { +				if (PIM_DEBUG_PIM_HELLO) { +					zlog_debug( +						"%s: could not sent PIM hello v6 secondary Address List option for interface %s", +						__PRETTY_FUNCTION__, ifp->name); +				} +				return -4; +			} +		} +	} -  return curr - tlv_buf; +	return curr - tlv_buf;  }  /* @@ -544,16 +544,16 @@ int pim_hello_build_tlv(struct interface *ifp,  */  void pim_hello_require(struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  zassert(ifp); +	zassert(ifp); -  pim_ifp = ifp->info; +	pim_ifp = ifp->info; -  zassert(pim_ifp); +	zassert(pim_ifp); -  if (pim_ifp->pim_ifstat_hello_sent) -    return; +	if (pim_ifp->pim_ifstat_hello_sent) +		return; -  pim_hello_restart_now(ifp); /* Send hello and restart timer */ +	pim_hello_restart_now(ifp); /* Send hello and restart timer */  } diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index ff799b20f8..df41f97d9e 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -24,17 +24,13 @@  #include "if.h" -int pim_hello_recv(struct interface *ifp, -		   struct in_addr src_addr, +int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,  		   uint8_t *tlv_buf, int tlv_buf_size); -int pim_hello_build_tlv(struct interface *ifp, -			uint8_t *tlv_buf, int tlv_buf_size, -			uint16_t holdtime, -			uint32_t dr_priority, -			uint32_t generation_id, -			uint16_t propagation_delay, -			uint16_t override_interval, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, +			int tlv_buf_size, uint16_t holdtime, +			uint32_t dr_priority, uint32_t generation_id, +			uint16_t propagation_delay, uint16_t override_interval,  			int can_disable_join_suppression);  void pim_hello_require(struct interface *ifp); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index f4125af9b4..8201625245 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -50,907 +50,919 @@ static int pim_iface_vif_index[MAXVIFS];  static void pim_if_igmp_join_del_all(struct interface *ifp);  static int igmp_join_sock(const char *ifname, ifindex_t ifindex, -			  struct in_addr group_addr, struct in_addr source_addr); +			  struct in_addr group_addr, +			  struct in_addr source_addr); -void -pim_if_init (void) +void pim_if_init(void)  { -  int i; +	int i; -  for (i = 0; i < MAXVIFS; i++) -    pim_iface_vif_index[i] = 0; +	for (i = 0; i < MAXVIFS; i++) +		pim_iface_vif_index[i] = 0; -  pim_ifchannel_list = list_new(); -  pim_ifchannel_list->cmp = (int (*)(void *, void *))pim_ifchannel_compare; +	pim_ifchannel_list = list_new(); +	pim_ifchannel_list->cmp = +		(int (*)(void *, void *))pim_ifchannel_compare;  } -void -pim_if_terminate (void) +void pim_if_terminate(void)  { -  if (pim_ifchannel_list) -    list_free (pim_ifchannel_list); +	if (pim_ifchannel_list) +		list_free(pim_ifchannel_list);  }  static void *if_list_clean(struct pim_interface *pim_ifp)  { -  if (pim_ifp->igmp_join_list) { -    list_delete(pim_ifp->igmp_join_list); -  } +	if (pim_ifp->igmp_join_list) { +		list_delete(pim_ifp->igmp_join_list); +	} -  if (pim_ifp->igmp_socket_list) { -    list_delete(pim_ifp->igmp_socket_list); -  } +	if (pim_ifp->igmp_socket_list) { +		list_delete(pim_ifp->igmp_socket_list); +	} -  if (pim_ifp->pim_neighbor_list) { -    list_delete(pim_ifp->pim_neighbor_list); -  } +	if (pim_ifp->pim_neighbor_list) { +		list_delete(pim_ifp->pim_neighbor_list); +	} -  if (pim_ifp->upstream_switch_list) -    list_delete(pim_ifp->upstream_switch_list); +	if (pim_ifp->upstream_switch_list) +		list_delete(pim_ifp->upstream_switch_list); -  if (pim_ifp->pim_ifchannel_list) { -    list_delete(pim_ifp->pim_ifchannel_list); -  } +	if (pim_ifp->pim_ifchannel_list) { +		list_delete(pim_ifp->pim_ifchannel_list); +	} -  if (pim_ifp->pim_ifchannel_hash) -    hash_free(pim_ifp->pim_ifchannel_hash); +	if (pim_ifp->pim_ifchannel_hash) +		hash_free(pim_ifp->pim_ifchannel_hash); -  XFREE(MTYPE_PIM_INTERFACE, pim_ifp); +	XFREE(MTYPE_PIM_INTERFACE, pim_ifp); -  return 0; +	return 0;  }  struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)  { -  struct pim_interface *pim_ifp; - -  zassert(ifp); -  zassert(!ifp->info); - -  pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); -  if (!pim_ifp) { -    zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); -    return 0; -  } - -  pim_ifp->options                           = 0; -  pim_ifp->mroute_vif_index                  = -1; - -  pim_ifp->igmp_version                               = IGMP_DEFAULT_VERSION; -  pim_ifp->igmp_default_robustness_variable           = IGMP_DEFAULT_ROBUSTNESS_VARIABLE; -  pim_ifp->igmp_default_query_interval                = IGMP_GENERAL_QUERY_INTERVAL; -  pim_ifp->igmp_query_max_response_time_dsec          = IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; -  pim_ifp->igmp_specific_query_max_response_time_dsec = IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; - -  /* -    RFC 3376: 8.3. Query Response Interval -    The number of seconds represented by the [Query Response Interval] -    must be less than the [Query Interval]. -   */ -  zassert(pim_ifp->igmp_query_max_response_time_dsec < pim_ifp->igmp_default_query_interval); - -  if (pim) -    PIM_IF_DO_PIM(pim_ifp->options); -  if (igmp) -    PIM_IF_DO_IGMP(pim_ifp->options); - -  PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); - -  pim_ifp->igmp_join_list = NULL; -  pim_ifp->igmp_socket_list = NULL; -  pim_ifp->pim_neighbor_list = NULL; -  pim_ifp->upstream_switch_list = NULL; -  pim_ifp->pim_ifchannel_list = NULL; -  pim_ifp->pim_ifchannel_hash = NULL; -  pim_ifp->pim_generation_id = 0; - -  /* list of struct igmp_sock */ -  pim_ifp->igmp_socket_list = list_new(); -  if (!pim_ifp->igmp_socket_list) { -    zlog_err("%s %s: failure: igmp_socket_list=list_new()", -	     __FILE__, __PRETTY_FUNCTION__); -    return if_list_clean(pim_ifp); -  } -  pim_ifp->igmp_socket_list->del = (void (*)(void *)) igmp_sock_free; - -  /* list of struct pim_neighbor */ -  pim_ifp->pim_neighbor_list = list_new(); -  if (!pim_ifp->pim_neighbor_list) { -    zlog_err("%s %s: failure: pim_neighbor_list=list_new()", -	     __FILE__, __PRETTY_FUNCTION__); -    return if_list_clean(pim_ifp); -  } -  pim_ifp->pim_neighbor_list->del = (void (*)(void *)) pim_neighbor_free; - -  pim_ifp->upstream_switch_list = list_new(); -  if (!pim_ifp->upstream_switch_list) { -    zlog_err("%s %s: failure: upstream_switch_list=list_new()", -             __FILE__, __PRETTY_FUNCTION__); -    return if_list_clean(pim_ifp); -  } - -  /* list of struct pim_ifchannel */ -  pim_ifp->pim_ifchannel_list = list_new(); -  if (!pim_ifp->pim_ifchannel_list) { -    zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", -	     __FILE__, __PRETTY_FUNCTION__); -    return if_list_clean(pim_ifp); -  } -  pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free; -  pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare; - -  pim_ifp->pim_ifchannel_hash = hash_create (pim_ifchannel_hash_key, -                                             pim_ifchannel_equal, NULL); - -  ifp->info = pim_ifp; - -  pim_sock_reset(ifp); - -  pim_if_add_vif(ifp); - -  return pim_ifp; +	struct pim_interface *pim_ifp; + +	zassert(ifp); +	zassert(!ifp->info); + +	pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); +	if (!pim_ifp) { +		zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); +		return 0; +	} + +	pim_ifp->options = 0; +	pim_ifp->mroute_vif_index = -1; + +	pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; +	pim_ifp->igmp_default_robustness_variable = +		IGMP_DEFAULT_ROBUSTNESS_VARIABLE; +	pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; +	pim_ifp->igmp_query_max_response_time_dsec = +		IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; +	pim_ifp->igmp_specific_query_max_response_time_dsec = +		IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; + +	/* +	  RFC 3376: 8.3. Query Response Interval +	  The number of seconds represented by the [Query Response Interval] +	  must be less than the [Query Interval]. +	 */ +	zassert(pim_ifp->igmp_query_max_response_time_dsec +		< pim_ifp->igmp_default_query_interval); + +	if (pim) +		PIM_IF_DO_PIM(pim_ifp->options); +	if (igmp) +		PIM_IF_DO_IGMP(pim_ifp->options); + +	PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); + +	pim_ifp->igmp_join_list = NULL; +	pim_ifp->igmp_socket_list = NULL; +	pim_ifp->pim_neighbor_list = NULL; +	pim_ifp->upstream_switch_list = NULL; +	pim_ifp->pim_ifchannel_list = NULL; +	pim_ifp->pim_ifchannel_hash = NULL; +	pim_ifp->pim_generation_id = 0; + +	/* list of struct igmp_sock */ +	pim_ifp->igmp_socket_list = list_new(); +	if (!pim_ifp->igmp_socket_list) { +		zlog_err("%s %s: failure: igmp_socket_list=list_new()", +			 __FILE__, __PRETTY_FUNCTION__); +		return if_list_clean(pim_ifp); +	} +	pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free; + +	/* list of struct pim_neighbor */ +	pim_ifp->pim_neighbor_list = list_new(); +	if (!pim_ifp->pim_neighbor_list) { +		zlog_err("%s %s: failure: pim_neighbor_list=list_new()", +			 __FILE__, __PRETTY_FUNCTION__); +		return if_list_clean(pim_ifp); +	} +	pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free; + +	pim_ifp->upstream_switch_list = list_new(); +	if (!pim_ifp->upstream_switch_list) { +		zlog_err("%s %s: failure: upstream_switch_list=list_new()", +			 __FILE__, __PRETTY_FUNCTION__); +		return if_list_clean(pim_ifp); +	} + +	/* list of struct pim_ifchannel */ +	pim_ifp->pim_ifchannel_list = list_new(); +	if (!pim_ifp->pim_ifchannel_list) { +		zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", +			 __FILE__, __PRETTY_FUNCTION__); +		return if_list_clean(pim_ifp); +	} +	pim_ifp->pim_ifchannel_list->del = (void (*)(void *))pim_ifchannel_free; +	pim_ifp->pim_ifchannel_list->cmp = +		(int (*)(void *, void *))pim_ifchannel_compare; + +	pim_ifp->pim_ifchannel_hash = +		hash_create(pim_ifchannel_hash_key, pim_ifchannel_equal, NULL); + +	ifp->info = pim_ifp; + +	pim_sock_reset(ifp); + +	pim_if_add_vif(ifp); + +	return pim_ifp;  }  void pim_if_delete(struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  zassert(ifp); -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	zassert(ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  if (pim_ifp->igmp_join_list) { -    pim_if_igmp_join_del_all(ifp); -  } +	if (pim_ifp->igmp_join_list) { +		pim_if_igmp_join_del_all(ifp); +	} -  pim_ifchannel_delete_all (ifp); -  igmp_sock_delete_all (ifp); +	pim_ifchannel_delete_all(ifp); +	igmp_sock_delete_all(ifp); -  pim_neighbor_delete_all (ifp, "Interface removed from configuration"); +	pim_neighbor_delete_all(ifp, "Interface removed from configuration"); -  pim_if_del_vif(ifp); +	pim_if_del_vif(ifp); -  list_delete(pim_ifp->igmp_socket_list); -  list_delete(pim_ifp->pim_neighbor_list); -  list_delete(pim_ifp->upstream_switch_list); -  list_delete(pim_ifp->pim_ifchannel_list); +	list_delete(pim_ifp->igmp_socket_list); +	list_delete(pim_ifp->pim_neighbor_list); +	list_delete(pim_ifp->upstream_switch_list); +	list_delete(pim_ifp->pim_ifchannel_list); -  hash_free (pim_ifp->pim_ifchannel_hash); +	hash_free(pim_ifp->pim_ifchannel_hash); -  XFREE(MTYPE_PIM_INTERFACE, pim_ifp); +	XFREE(MTYPE_PIM_INTERFACE, pim_ifp); -  ifp->info = NULL; +	ifp->info = NULL;  }  void pim_if_update_could_assert(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct listnode      *next_node; -  struct pim_ifchannel *ch; +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct listnode *next_node; +	struct pim_ifchannel *ch; -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { -    pim_ifchannel_update_could_assert(ch); -  } +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, +			       ch)) { +		pim_ifchannel_update_could_assert(ch); +	}  }  static void pim_if_update_my_assert_metric(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct listnode      *next_node; -  struct pim_ifchannel *ch; +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct listnode *next_node; +	struct pim_ifchannel *ch; -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { -    pim_ifchannel_update_my_assert_metric(ch); -  } +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, +			       ch)) { +		pim_ifchannel_update_my_assert_metric(ch); +	}  }  static void pim_addr_change(struct interface *ifp)  { -  struct pim_interface *pim_ifp; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- Done TODO T30 */ -  pim_if_update_join_desired(pim_ifp); /* depends on DR */ -  pim_if_update_could_assert(ifp); /* depends on DR */ -  pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ -  pim_if_update_assert_tracking_desired(ifp); /* depends on DR, join_desired */ - -  /* -    RFC 4601: 4.3.1.  Sending Hello Messages - -    1) Before an interface goes down or changes primary IP address, a -    Hello message with a zero HoldTime should be sent immediately -    (with the old IP address if the IP address changed). -    -- FIXME See CAVEAT C13 - -    2) After an interface has changed its IP address, it MUST send a -    Hello message with its new IP address. -    -- DONE below - -    3) If an interface changes one of its secondary IP addresses, a -    Hello message with an updated Address_List option and a non-zero -    HoldTime should be sent immediately. -    -- FIXME See TODO T31 -   */ -  pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ -  if (pim_ifp->pim_sock_fd < 0) -    return; -  pim_hello_restart_now(ifp);         /* send hello and restart timer */ +	struct pim_interface *pim_ifp; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- +				    Done TODO T30 */ +	pim_if_update_join_desired(pim_ifp); /* depends on DR */ +	pim_if_update_could_assert(ifp);     /* depends on DR */ +	pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ +	pim_if_update_assert_tracking_desired( +		ifp); /* depends on DR, join_desired */ + +	/* +	  RFC 4601: 4.3.1.  Sending Hello Messages + +	  1) Before an interface goes down or changes primary IP address, a +	  Hello message with a zero HoldTime should be sent immediately +	  (with the old IP address if the IP address changed). +	  -- FIXME See CAVEAT C13 + +	  2) After an interface has changed its IP address, it MUST send a +	  Hello message with its new IP address. +	  -- DONE below + +	  3) If an interface changes one of its secondary IP addresses, a +	  Hello message with an updated Address_List option and a non-zero +	  HoldTime should be sent immediately. +	  -- FIXME See TODO T31 +	 */ +	pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ +	if (pim_ifp->pim_sock_fd < 0) +		return; +	pim_hello_restart_now(ifp); /* send hello and restart timer */  }  static int detect_primary_address_change(struct interface *ifp,  					 int force_prim_as_any,  					 const char *caller)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct in_addr new_prim_addr; -  int changed; - -  if (force_prim_as_any) -    new_prim_addr.s_addr = INADDR_ANY; -  else -    new_prim_addr = pim_find_primary_addr(ifp); - -  changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; - -  if (PIM_DEBUG_ZEBRA) { -    char new_prim_str[INET_ADDRSTRLEN]; -    char old_prim_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<new?>", new_prim_addr, new_prim_str, sizeof(new_prim_str)); -    pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str, sizeof(old_prim_str)); -    zlog_debug("%s: old=%s new=%s on interface %s: %s", -	       __PRETTY_FUNCTION__,  -	       old_prim_str, new_prim_str, ifp->name, -	       changed ? "changed" : "unchanged"); -  } - -  if (changed) { -    pim_ifp->primary_address = new_prim_addr; -  } - -  return changed; +	struct pim_interface *pim_ifp = ifp->info; +	struct in_addr new_prim_addr; +	int changed; + +	if (force_prim_as_any) +		new_prim_addr.s_addr = INADDR_ANY; +	else +		new_prim_addr = pim_find_primary_addr(ifp); + +	changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; + +	if (PIM_DEBUG_ZEBRA) { +		char new_prim_str[INET_ADDRSTRLEN]; +		char old_prim_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<new?>", new_prim_addr, new_prim_str, +			       sizeof(new_prim_str)); +		pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str, +			       sizeof(old_prim_str)); +		zlog_debug("%s: old=%s new=%s on interface %s: %s", +			   __PRETTY_FUNCTION__, old_prim_str, new_prim_str, +			   ifp->name, changed ? "changed" : "unchanged"); +	} + +	if (changed) { +		pim_ifp->primary_address = new_prim_addr; +	} + +	return changed;  }  static int pim_sec_addr_comp(const void *p1, const void *p2)  { -  const struct pim_secondary_addr *sec1 = p1; -  const struct pim_secondary_addr *sec2 = p2; - -  if (sec1->addr.family == AF_INET && -      sec2->addr.family == AF_INET6) -    return -1; - -  if (sec1->addr.family == AF_INET6 && -      sec2->addr.family == AF_INET) -    return 1; - -  if (sec1->addr.family == AF_INET) -    { -      if (ntohl(sec1->addr.u.prefix4.s_addr) < ntohl(sec2->addr.u.prefix4.s_addr)) -        return -1; - -      if (ntohl(sec1->addr.u.prefix4.s_addr) > ntohl(sec2->addr.u.prefix4.s_addr)) -        return 1; -    } -  else -    { -      return memcmp (&sec1->addr.u.prefix6, -                     &sec2->addr.u.prefix6, -                     sizeof (struct in6_addr)); -    } - -  return 0; +	const struct pim_secondary_addr *sec1 = p1; +	const struct pim_secondary_addr *sec2 = p2; + +	if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6) +		return -1; + +	if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET) +		return 1; + +	if (sec1->addr.family == AF_INET) { +		if (ntohl(sec1->addr.u.prefix4.s_addr) +		    < ntohl(sec2->addr.u.prefix4.s_addr)) +			return -1; + +		if (ntohl(sec1->addr.u.prefix4.s_addr) +		    > ntohl(sec2->addr.u.prefix4.s_addr)) +			return 1; +	} else { +		return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6, +			      sizeof(struct in6_addr)); +	} + +	return 0;  }  static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)  { -  XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); +	XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);  }  static struct pim_secondary_addr *  pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)  { -  struct pim_secondary_addr *sec_addr; -  struct listnode *node; +	struct pim_secondary_addr *sec_addr; +	struct listnode *node; -  if (!pim_ifp->sec_addr_list) { -    return NULL; -  } +	if (!pim_ifp->sec_addr_list) { +		return NULL; +	} -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { -    if (prefix_cmp(&sec_addr->addr, addr)) { -      return sec_addr; -    } -  } +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { +		if (prefix_cmp(&sec_addr->addr, addr)) { +			return sec_addr; +		} +	} -  return NULL; +	return NULL;  }  static void pim_sec_addr_del(struct pim_interface *pim_ifp, -                             struct pim_secondary_addr *sec_addr) +			     struct pim_secondary_addr *sec_addr)  { -  listnode_delete(pim_ifp->sec_addr_list, sec_addr); -  pim_sec_addr_free(sec_addr); +	listnode_delete(pim_ifp->sec_addr_list, sec_addr); +	pim_sec_addr_free(sec_addr);  }  static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)  { -  int changed = 0; -  struct pim_secondary_addr *sec_addr; - -  sec_addr = pim_sec_addr_find(pim_ifp, addr); -  if (sec_addr) { -    sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; -    return changed; -  } - -  if (!pim_ifp->sec_addr_list) { -    pim_ifp->sec_addr_list = list_new(); -    pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free; -    pim_ifp->sec_addr_list->cmp = (int (*)(void *, void *))pim_sec_addr_comp; -  } - -  sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); -  if (!sec_addr) { -    if (list_isempty(pim_ifp->sec_addr_list)) { -      list_free(pim_ifp->sec_addr_list); -      pim_ifp->sec_addr_list = NULL; -    } -    return changed; -  } - -  changed = 1; -  sec_addr->addr = *addr; -  listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); - -  return changed; +	int changed = 0; +	struct pim_secondary_addr *sec_addr; + +	sec_addr = pim_sec_addr_find(pim_ifp, addr); +	if (sec_addr) { +		sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; +		return changed; +	} + +	if (!pim_ifp->sec_addr_list) { +		pim_ifp->sec_addr_list = list_new(); +		pim_ifp->sec_addr_list->del = +			(void (*)(void *))pim_sec_addr_free; +		pim_ifp->sec_addr_list->cmp = +			(int (*)(void *, void *))pim_sec_addr_comp; +	} + +	sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); +	if (!sec_addr) { +		if (list_isempty(pim_ifp->sec_addr_list)) { +			list_free(pim_ifp->sec_addr_list); +			pim_ifp->sec_addr_list = NULL; +		} +		return changed; +	} + +	changed = 1; +	sec_addr->addr = *addr; +	listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); + +	return changed;  }  static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)  { -  int changed = 0; - -  if (!pim_ifp->sec_addr_list) { -    return changed; -  } -  if (!list_isempty(pim_ifp->sec_addr_list)) { -    changed = 1; -    /* remove all nodes and free up the list itself */ -    list_delete_all_node(pim_ifp->sec_addr_list); -    list_free(pim_ifp->sec_addr_list); -    pim_ifp->sec_addr_list = NULL; -  } - -  return changed; +	int changed = 0; + +	if (!pim_ifp->sec_addr_list) { +		return changed; +	} +	if (!list_isempty(pim_ifp->sec_addr_list)) { +		changed = 1; +		/* remove all nodes and free up the list itself */ +		list_delete_all_node(pim_ifp->sec_addr_list); +		list_free(pim_ifp->sec_addr_list); +		pim_ifp->sec_addr_list = NULL; +	} + +	return changed;  }  static int pim_sec_addr_update(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct connected *ifc; -  struct listnode *node; -  struct listnode *nextnode; -  struct pim_secondary_addr *sec_addr; -  int changed = 0; - -  if (pim_ifp->sec_addr_list) { -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { -      sec_addr->flags |= PIM_SEC_ADDRF_STALE; -    } -  } - -  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { -    struct prefix *p = ifc->address; - -    if (PIM_INADDR_IS_ANY(p->u.prefix4)) { -      continue; -    } - -    if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { -      /* don't add the primary address into the secondary address list */ -      continue; -    } - -    if (pim_sec_addr_add(pim_ifp, p)) { -      changed = 1; -    } -  } - -  if (pim_ifp->sec_addr_list) { -    /* Drop stale entries */ -    for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, sec_addr)) { -      if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { -        pim_sec_addr_del(pim_ifp, sec_addr); -        changed = 1; -      } -    } - -    /* If the list went empty free it up */ -    if (list_isempty(pim_ifp->sec_addr_list)) { -      list_free(pim_ifp->sec_addr_list); -      pim_ifp->sec_addr_list = NULL; -    } -  } - -  return changed; +	struct pim_interface *pim_ifp = ifp->info; +	struct connected *ifc; +	struct listnode *node; +	struct listnode *nextnode; +	struct pim_secondary_addr *sec_addr; +	int changed = 0; + +	if (pim_ifp->sec_addr_list) { +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, +					  sec_addr)) { +			sec_addr->flags |= PIM_SEC_ADDRF_STALE; +		} +	} + +	for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { +		struct prefix *p = ifc->address; + +		if (PIM_INADDR_IS_ANY(p->u.prefix4)) { +			continue; +		} + +		if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { +			/* don't add the primary address into the secondary +			 * address list */ +			continue; +		} + +		if (pim_sec_addr_add(pim_ifp, p)) { +			changed = 1; +		} +	} + +	if (pim_ifp->sec_addr_list) { +		/* Drop stale entries */ +		for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, +				       sec_addr)) { +			if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { +				pim_sec_addr_del(pim_ifp, sec_addr); +				changed = 1; +			} +		} + +		/* If the list went empty free it up */ +		if (list_isempty(pim_ifp->sec_addr_list)) { +			list_free(pim_ifp->sec_addr_list); +			pim_ifp->sec_addr_list = NULL; +		} +	} + +	return changed;  }  static int detect_secondary_address_change(struct interface *ifp, -              int force_prim_as_any, -					    const char *caller) +					   int force_prim_as_any, +					   const char *caller)  { -  struct pim_interface *pim_ifp = ifp->info; -  int changed = 0; - -  if (force_prim_as_any) { -    /* if primary address is being forced to zero just flush the -     * secondary address list */ -    changed = pim_sec_addr_del_all(pim_ifp); -  } else { -    /* re-evaluate the secondary address list */ -    changed = pim_sec_addr_update(ifp); -  } - -  return changed; +	struct pim_interface *pim_ifp = ifp->info; +	int changed = 0; + +	if (force_prim_as_any) { +		/* if primary address is being forced to zero just flush the +		 * secondary address list */ +		changed = pim_sec_addr_del_all(pim_ifp); +	} else { +		/* re-evaluate the secondary address list */ +		changed = pim_sec_addr_update(ifp); +	} + +	return changed;  } -static void detect_address_change(struct interface *ifp, -				 int force_prim_as_any, -				 const char *caller) +static void detect_address_change(struct interface *ifp, int force_prim_as_any, +				  const char *caller)  { -  int changed = 0; -  struct pim_interface *pim_ifp; +	int changed = 0; +	struct pim_interface *pim_ifp; -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return; +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return; -  if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { -    changed = 1; -  } +	if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { +		changed = 1; +	} -  if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { -    changed = 1; -  } +	if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { +		changed = 1; +	} -  if (changed) { -    if (!PIM_IF_TEST_PIM(pim_ifp->options)) { -      return; -    } +	if (changed) { +		if (!PIM_IF_TEST_PIM(pim_ifp->options)) { +			return; +		} -    pim_addr_change(ifp); -  } +		pim_addr_change(ifp); +	} -  /* XXX: if we have unnumbered interfaces we need to run detect address -   * address change on all of them when the lo address changes */ +	/* XXX: if we have unnumbered interfaces we need to run detect address +	 * address change on all of them when the lo address changes */  }  int pim_update_source_set(struct interface *ifp, struct in_addr source)  { -  struct pim_interface *pim_ifp = ifp->info; +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp) { -    return PIM_IFACE_NOT_FOUND; -  } +	if (!pim_ifp) { +		return PIM_IFACE_NOT_FOUND; +	} -  if (pim_ifp->update_source.s_addr == source.s_addr) { -    return PIM_UPDATE_SOURCE_DUP; -  } +	if (pim_ifp->update_source.s_addr == source.s_addr) { +		return PIM_UPDATE_SOURCE_DUP; +	} -  pim_ifp->update_source = source; -  detect_address_change(ifp, 0 /* force_prim_as_any */, -                        __PRETTY_FUNCTION__); +	pim_ifp->update_source = source; +	detect_address_change(ifp, 0 /* force_prim_as_any */, +			      __PRETTY_FUNCTION__); -  return PIM_SUCCESS; +	return PIM_SUCCESS;  }  void pim_if_addr_add(struct connected *ifc)  { -  struct pim_interface *pim_ifp; -  struct interface *ifp; -  struct in_addr ifaddr; - -  zassert(ifc); - -  ifp = ifc->ifp; -  zassert(ifp); -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return; - -  if (!if_is_operative(ifp)) -    return; - -  if (PIM_DEBUG_ZEBRA) { -    char buf[BUFSIZ]; -    prefix2str(ifc->address, buf, BUFSIZ); -    zlog_debug("%s: %s ifindex=%d connected IP address %s %s", -	       __PRETTY_FUNCTION__, -	       ifp->name, ifp->ifindex, buf, -	       CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? -	       "secondary" : "primary"); -  } - -  ifaddr = ifc->address->u.prefix4; - -  detect_address_change(ifp, 0, __PRETTY_FUNCTION__); - -  if (ifc->address->family != AF_INET) -    return; - -  if (PIM_IF_TEST_IGMP(pim_ifp->options)) { -    struct igmp_sock *igmp; - -    /* lookup IGMP socket */ -    igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, -                                       ifaddr); -    if (!igmp) { -      /* if addr new, add IGMP socket */ -      pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp); -    } - -    /* Replay Static IGMP groups */ -    if (pim_ifp->igmp_join_list) -      { -        struct listnode *node; -        struct listnode *nextnode; -        struct igmp_join *ij; -        int join_fd; - -        for (ALL_LIST_ELEMENTS (pim_ifp->igmp_join_list, node, nextnode, ij)) -          { -            /* Close socket and reopen with Source and Group */ -            close(ij->sock_fd); -            join_fd = igmp_join_sock(ifp->name, ifp->ifindex, ij->group_addr, ij->source_addr); -            if (join_fd < 0) -              { -                char group_str[INET_ADDRSTRLEN]; -                char source_str[INET_ADDRSTRLEN]; -                pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str)); -                pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str)); -                zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", -	              __PRETTY_FUNCTION__, -	              group_str, source_str, ifp->name); -                /* warning only */ -              } -            else -              ij->sock_fd = join_fd; -          } -      } -  } /* igmp */ - -  if (PIM_IF_TEST_PIM(pim_ifp->options)) -    { - -      if (PIM_INADDR_ISNOT_ANY (pim_ifp->primary_address)) -        { - -          /* Interface has a valid socket ? */ -          if (pim_ifp->pim_sock_fd < 0) -            { -              if (pim_sock_add (ifp)) -                { -                  zlog_warn ("Failure creating PIM socket for interface %s", -                             ifp->name); -                } -            } -          struct pim_nexthop_cache *pnc = NULL; -          struct pim_rpf rpf; -          struct zclient *zclient = NULL; - -          zclient = pim_zebra_zclient_get (); -          /* RP config might come prior to (local RP's interface) IF UP event. -             In this case, pnc would not have pim enabled nexthops. -             Once Interface is UP and pim info is available, reregister -             with RNH address to receive update and add the interface as nexthop. */ -          memset (&rpf, 0, sizeof (struct pim_rpf)); -          rpf.rpf_addr.family = AF_INET; -          rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; -          rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; -          pnc = pim_nexthop_cache_find (&rpf); -          if (pnc) -            pim_sendmsg_zebra_rnh (zclient, pnc, -                                   ZEBRA_NEXTHOP_REGISTER); -        } -    } /* pim */ - -    /* -      PIM or IGMP is enabled on interface, and there is at least one -      address assigned, then try to create a vif_index. -    */ -  if (pim_ifp->mroute_vif_index < 0) { -    pim_if_add_vif(ifp); -  } -  pim_ifchannel_scan_forward_start (ifp); +	struct pim_interface *pim_ifp; +	struct interface *ifp; +	struct in_addr ifaddr; + +	zassert(ifc); + +	ifp = ifc->ifp; +	zassert(ifp); +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return; + +	if (!if_is_operative(ifp)) +		return; + +	if (PIM_DEBUG_ZEBRA) { +		char buf[BUFSIZ]; +		prefix2str(ifc->address, buf, BUFSIZ); +		zlog_debug("%s: %s ifindex=%d connected IP address %s %s", +			   __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, +			   CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) +				   ? "secondary" +				   : "primary"); +	} + +	ifaddr = ifc->address->u.prefix4; + +	detect_address_change(ifp, 0, __PRETTY_FUNCTION__); + +	if (ifc->address->family != AF_INET) +		return; + +	if (PIM_IF_TEST_IGMP(pim_ifp->options)) { +		struct igmp_sock *igmp; + +		/* lookup IGMP socket */ +		igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, +						   ifaddr); +		if (!igmp) { +			/* if addr new, add IGMP socket */ +			pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, +					  ifp); +		} + +		/* Replay Static IGMP groups */ +		if (pim_ifp->igmp_join_list) { +			struct listnode *node; +			struct listnode *nextnode; +			struct igmp_join *ij; +			int join_fd; + +			for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, +					       nextnode, ij)) { +				/* Close socket and reopen with Source and Group +				 */ +				close(ij->sock_fd); +				join_fd = igmp_join_sock( +					ifp->name, ifp->ifindex, ij->group_addr, +					ij->source_addr); +				if (join_fd < 0) { +					char group_str[INET_ADDRSTRLEN]; +					char source_str[INET_ADDRSTRLEN]; +					pim_inet4_dump("<grp?>", ij->group_addr, +						       group_str, +						       sizeof(group_str)); +					pim_inet4_dump( +						"<src?>", ij->source_addr, +						source_str, sizeof(source_str)); +					zlog_warn( +						"%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", +						__PRETTY_FUNCTION__, group_str, +						source_str, ifp->name); +					/* warning only */ +				} else +					ij->sock_fd = join_fd; +			} +		} +	} /* igmp */ + +	if (PIM_IF_TEST_PIM(pim_ifp->options)) { + +		if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + +			/* Interface has a valid socket ? */ +			if (pim_ifp->pim_sock_fd < 0) { +				if (pim_sock_add(ifp)) { +					zlog_warn( +						"Failure creating PIM socket for interface %s", +						ifp->name); +				} +			} +			struct pim_nexthop_cache *pnc = NULL; +			struct pim_rpf rpf; +			struct zclient *zclient = NULL; + +			zclient = pim_zebra_zclient_get(); +			/* RP config might come prior to (local RP's interface) +			   IF UP event. +			   In this case, pnc would not have pim enabled +			   nexthops. +			   Once Interface is UP and pim info is available, +			   reregister +			   with RNH address to receive update and add the +			   interface as nexthop. */ +			memset(&rpf, 0, sizeof(struct pim_rpf)); +			rpf.rpf_addr.family = AF_INET; +			rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; +			rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; +			pnc = pim_nexthop_cache_find(&rpf); +			if (pnc) +				pim_sendmsg_zebra_rnh(zclient, pnc, +						      ZEBRA_NEXTHOP_REGISTER); +		} +	} /* pim */ + +	/* +	  PIM or IGMP is enabled on interface, and there is at least one +	  address assigned, then try to create a vif_index. +	*/ +	if (pim_ifp->mroute_vif_index < 0) { +		pim_if_add_vif(ifp); +	} +	pim_ifchannel_scan_forward_start(ifp);  }  static void pim_if_addr_del_igmp(struct connected *ifc)  { -  struct pim_interface *pim_ifp = ifc->ifp->info; -  struct igmp_sock *igmp; -  struct in_addr ifaddr; - -  if (ifc->address->family != AF_INET) { -    /* non-IPv4 address */ -    return; -  } - -  if (!pim_ifp) { -    /* IGMP not enabled on interface */ -    return; -  } - -  ifaddr = ifc->address->u.prefix4; - -  /* lookup IGMP socket */ -  igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, -				     ifaddr); -  if (igmp) { -    /* if addr found, del IGMP socket */ -    igmp_sock_delete(igmp); -  } +	struct pim_interface *pim_ifp = ifc->ifp->info; +	struct igmp_sock *igmp; +	struct in_addr ifaddr; + +	if (ifc->address->family != AF_INET) { +		/* non-IPv4 address */ +		return; +	} + +	if (!pim_ifp) { +		/* IGMP not enabled on interface */ +		return; +	} + +	ifaddr = ifc->address->u.prefix4; + +	/* lookup IGMP socket */ +	igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); +	if (igmp) { +		/* if addr found, del IGMP socket */ +		igmp_sock_delete(igmp); +	}  }  static void pim_if_addr_del_pim(struct connected *ifc)  { -  struct pim_interface *pim_ifp = ifc->ifp->info; - -  if (ifc->address->family != AF_INET) { -    /* non-IPv4 address */ -    return; -  } - -  if (!pim_ifp) { -    /* PIM not enabled on interface */ -    return; -  } - -  if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { -    /* Interface keeps a valid primary address */ -    return; -  } - -  if (pim_ifp->pim_sock_fd < 0) { -    /* Interface does not hold a valid socket any longer */ -    return; -  } - -  /* -    pim_sock_delete() closes the socket, stops read and timer threads, -    and kills all neighbors. -   */ -  pim_sock_delete(ifc->ifp, "last address has been removed from interface"); -} +	struct pim_interface *pim_ifp = ifc->ifp->info; -void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) -{ -  struct interface *ifp; +	if (ifc->address->family != AF_INET) { +		/* non-IPv4 address */ +		return; +	} -  zassert(ifc); -  ifp = ifc->ifp; -  zassert(ifp); +	if (!pim_ifp) { +		/* PIM not enabled on interface */ +		return; +	} + +	if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { +		/* Interface keeps a valid primary address */ +		return; +	} -  if (ifc->address->family != AF_INET) -    return; +	if (pim_ifp->pim_sock_fd < 0) { +		/* Interface does not hold a valid socket any longer */ +		return; +	} -  if (PIM_DEBUG_ZEBRA) { -    char buf[BUFSIZ]; -    prefix2str(ifc->address, buf, BUFSIZ); -    zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", -               __PRETTY_FUNCTION__, -               ifp->name, ifp->ifindex, buf, -               CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? -               "secondary" : "primary"); -  } +	/* +	  pim_sock_delete() closes the socket, stops read and timer threads, +	  and kills all neighbors. +	 */ +	pim_sock_delete(ifc->ifp, +			"last address has been removed from interface"); +} -  detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); +void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) +{ +	struct interface *ifp; + +	zassert(ifc); +	ifp = ifc->ifp; +	zassert(ifp); + +	if (ifc->address->family != AF_INET) +		return; + +	if (PIM_DEBUG_ZEBRA) { +		char buf[BUFSIZ]; +		prefix2str(ifc->address, buf, BUFSIZ); +		zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", +			   __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, +			   CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) +				   ? "secondary" +				   : "primary"); +	} -  pim_if_addr_del_igmp(ifc); -  pim_if_addr_del_pim(ifc); +	detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); + +	pim_if_addr_del_igmp(ifc); +	pim_if_addr_del_pim(ifc);  }  void pim_if_addr_add_all(struct interface *ifp)  { -  struct connected *ifc; -  struct listnode *node; -  struct listnode *nextnode; -  int v4_addrs = 0; -  int v6_addrs = 0; -  struct pim_interface *pim_ifp = ifp->info; - - -  /* PIM/IGMP enabled ? */ -  if (!pim_ifp) -    return; - -  for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { -    struct prefix *p = ifc->address; -     -    if (p->family != AF_INET) -      v6_addrs++; -    else -      v4_addrs++; -    pim_if_addr_add(ifc); -  } - -  if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) -    { -      if (PIM_IF_TEST_PIM(pim_ifp->options)) { - -	/* Interface has a valid primary address ? */ -	if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { +	struct connected *ifc; +	struct listnode *node; +	struct listnode *nextnode; +	int v4_addrs = 0; +	int v6_addrs = 0; +	struct pim_interface *pim_ifp = ifp->info; + + +	/* PIM/IGMP enabled ? */ +	if (!pim_ifp) +		return; + +	for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { +		struct prefix *p = ifc->address; + +		if (p->family != AF_INET) +			v6_addrs++; +		else +			v4_addrs++; +		pim_if_addr_add(ifc); +	} -	  /* Interface has a valid socket ? */ -	  if (pim_ifp->pim_sock_fd < 0) { -	    if (pim_sock_add(ifp)) { -	      zlog_warn("Failure creating PIM socket for interface %s", -			ifp->name); -	    } -	  } - -	} -      } /* pim */ -    } -  /* -   * PIM or IGMP is enabled on interface, and there is at least one -   * address assigned, then try to create a vif_index. -   */ -  if (pim_ifp->mroute_vif_index < 0) { -    pim_if_add_vif(ifp); -  } -  pim_ifchannel_scan_forward_start (ifp); - -  pim_rp_setup(); -  pim_rp_check_on_if_add(pim_ifp); +	if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { +		if (PIM_IF_TEST_PIM(pim_ifp->options)) { + +			/* Interface has a valid primary address ? */ +			if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + +				/* Interface has a valid socket ? */ +				if (pim_ifp->pim_sock_fd < 0) { +					if (pim_sock_add(ifp)) { +						zlog_warn( +							"Failure creating PIM socket for interface %s", +							ifp->name); +					} +				} +			} +		} /* pim */ +	} +	/* +	 * PIM or IGMP is enabled on interface, and there is at least one +	 * address assigned, then try to create a vif_index. +	 */ +	if (pim_ifp->mroute_vif_index < 0) { +		pim_if_add_vif(ifp); +	} +	pim_ifchannel_scan_forward_start(ifp); + +	pim_rp_setup(); +	pim_rp_check_on_if_add(pim_ifp);  }  void pim_if_addr_del_all(struct interface *ifp)  { -  struct connected *ifc; -  struct listnode *node; -  struct listnode *nextnode; +	struct connected *ifc; +	struct listnode *node; +	struct listnode *nextnode; + +	/* PIM/IGMP enabled ? */ +	if (!ifp->info) +		return; -  /* PIM/IGMP enabled ? */ -  if (!ifp->info) -    return; +	for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { +		struct prefix *p = ifc->address; -  for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { -    struct prefix *p = ifc->address; -     -    if (p->family != AF_INET) -      continue; +		if (p->family != AF_INET) +			continue; -    pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); -  } +		pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); +	} -  pim_rp_setup(); -  pim_i_am_rp_re_evaluate(); +	pim_rp_setup(); +	pim_i_am_rp_re_evaluate();  }  void pim_if_addr_del_all_igmp(struct interface *ifp)  { -  struct connected *ifc; -  struct listnode *node; -  struct listnode *nextnode; - -  /* PIM/IGMP enabled ? */ -  if (!ifp->info) -    return; - -  for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { -    struct prefix *p = ifc->address; -     -    if (p->family != AF_INET) -      continue; - -    pim_if_addr_del_igmp(ifc); -  } +	struct connected *ifc; +	struct listnode *node; +	struct listnode *nextnode; + +	/* PIM/IGMP enabled ? */ +	if (!ifp->info) +		return; + +	for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { +		struct prefix *p = ifc->address; + +		if (p->family != AF_INET) +			continue; + +		pim_if_addr_del_igmp(ifc); +	}  }  void pim_if_addr_del_all_pim(struct interface *ifp)  { -  struct connected *ifc; -  struct listnode *node; -  struct listnode *nextnode; - -  /* PIM/IGMP enabled ? */ -  if (!ifp->info) -    return; - -  for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { -    struct prefix *p = ifc->address; -     -    if (p->family != AF_INET) -      continue; - -    pim_if_addr_del_pim(ifc); -  } +	struct connected *ifc; +	struct listnode *node; +	struct listnode *nextnode; + +	/* PIM/IGMP enabled ? */ +	if (!ifp->info) +		return; + +	for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { +		struct prefix *p = ifc->address; + +		if (p->family != AF_INET) +			continue; + +		pim_if_addr_del_pim(ifc); +	}  } -struct in_addr -pim_find_primary_addr (struct interface *ifp) +struct in_addr pim_find_primary_addr(struct interface *ifp)  { -  struct connected *ifc; -  struct listnode *node; -  struct in_addr addr; -  int v4_addrs = 0; -  int v6_addrs = 0; -  struct pim_interface *pim_ifp = ifp->info; - -  if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { -    return pim_ifp->update_source; -  } - -  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { -    struct prefix *p = ifc->address; - -    if (p->family != AF_INET) -      { -	v6_addrs++; -	continue; -      } - -    if (PIM_INADDR_IS_ANY(p->u.prefix4)) { -      zlog_warn("%s: null IPv4 address connected to interface %s", -		__PRETTY_FUNCTION__, ifp->name); -      continue; -    } - -    v4_addrs++; - -    if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) -      continue; - -    return p->u.prefix4; -  } - -  /* -   * If we have no v4_addrs and v6 is configured -   * We probably are using unnumbered -   * So let's grab the loopbacks v4 address -   * and use that as the primary address -   */ -  if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) -    { -      struct interface *lo_ifp; -      lo_ifp = if_lookup_by_name ("lo", VRF_DEFAULT); -      if (lo_ifp) -	return pim_find_primary_addr (lo_ifp); -    } - -  addr.s_addr = PIM_NET_INADDR_ANY; - -  return addr; +	struct connected *ifc; +	struct listnode *node; +	struct in_addr addr; +	int v4_addrs = 0; +	int v6_addrs = 0; +	struct pim_interface *pim_ifp = ifp->info; + +	if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { +		return pim_ifp->update_source; +	} + +	for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { +		struct prefix *p = ifc->address; + +		if (p->family != AF_INET) { +			v6_addrs++; +			continue; +		} + +		if (PIM_INADDR_IS_ANY(p->u.prefix4)) { +			zlog_warn( +				"%s: null IPv4 address connected to interface %s", +				__PRETTY_FUNCTION__, ifp->name); +			continue; +		} + +		v4_addrs++; + +		if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) +			continue; + +		return p->u.prefix4; +	} + +	/* +	 * If we have no v4_addrs and v6 is configured +	 * We probably are using unnumbered +	 * So let's grab the loopbacks v4 address +	 * and use that as the primary address +	 */ +	if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { +		struct interface *lo_ifp; +		lo_ifp = if_lookup_by_name("lo", VRF_DEFAULT); +		if (lo_ifp) +			return pim_find_primary_addr(lo_ifp); +	} + +	addr.s_addr = PIM_NET_INADDR_ANY; + +	return addr;  } -static int -pim_iface_next_vif_index (struct interface *ifp) +static int pim_iface_next_vif_index(struct interface *ifp)  { -  int i; -  /* -   * The pimreg vif is always going to be in index 0 -   * of the table. -   */ -  if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) -    return 0; - -  for (i = 1 ; i < MAXVIFS; i++) -    { -      if (pim_iface_vif_index[i] == 0) -        return i; -    } -  return MAXVIFS; +	int i; +	/* +	 * The pimreg vif is always going to be in index 0 +	 * of the table. +	 */ +	if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) +		return 0; + +	for (i = 1; i < MAXVIFS; i++) { +		if (pim_iface_vif_index[i] == 0) +			return i; +	} +	return MAXVIFS;  }  /* @@ -960,130 +972,131 @@ pim_iface_next_vif_index (struct interface *ifp)   */  int pim_if_add_vif(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct in_addr ifaddr; -  unsigned char flags = 0; - -  zassert(pim_ifp); - -  if (pim_ifp->mroute_vif_index > 0) { -    zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", -	      __PRETTY_FUNCTION__, -	      pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); -    return -1; -  } - -  if (ifp->ifindex < 0) { -    zlog_warn("%s: ifindex=%d < 1 on interface %s", -	      __PRETTY_FUNCTION__, -	      ifp->ifindex, ifp->name); -    return -2; -  } - -  ifaddr = pim_ifp->primary_address; -  if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF && PIM_INADDR_IS_ANY(ifaddr)) { -    zlog_warn("%s: could not get address for interface %s ifindex=%d", -	      __PRETTY_FUNCTION__, -	      ifp->name, ifp->ifindex); -    return -4; -  } - -  pim_ifp->mroute_vif_index = pim_iface_next_vif_index (ifp); - -  if (pim_ifp->mroute_vif_index >= MAXVIFS) -    { -      zlog_warn("%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", -		__PRETTY_FUNCTION__, -		MAXVIFS, ifp->name); -      return -3; -    } - -  if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) -    flags = VIFF_REGISTER; +	struct pim_interface *pim_ifp = ifp->info; +	struct in_addr ifaddr; +	unsigned char flags = 0; + +	zassert(pim_ifp); + +	if (pim_ifp->mroute_vif_index > 0) { +		zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", +			  __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, +			  ifp->name, ifp->ifindex); +		return -1; +	} + +	if (ifp->ifindex < 0) { +		zlog_warn("%s: ifindex=%d < 1 on interface %s", +			  __PRETTY_FUNCTION__, ifp->ifindex, ifp->name); +		return -2; +	} + +	ifaddr = pim_ifp->primary_address; +	if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF +	    && PIM_INADDR_IS_ANY(ifaddr)) { +		zlog_warn( +			"%s: could not get address for interface %s ifindex=%d", +			__PRETTY_FUNCTION__, ifp->name, ifp->ifindex); +		return -4; +	} + +	pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp); + +	if (pim_ifp->mroute_vif_index >= MAXVIFS) { +		zlog_warn( +			"%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", +			__PRETTY_FUNCTION__, MAXVIFS, ifp->name); +		return -3; +	} + +	if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) +		flags = VIFF_REGISTER;  #ifdef VIFF_USE_IFINDEX -  else -    flags = VIFF_USE_IFINDEX; +	else +		flags = VIFF_USE_IFINDEX;  #endif -  if (pim_mroute_add_vif(ifp, ifaddr, flags)) { -    /* pim_mroute_add_vif reported error */ -    return -5; -  } +	if (pim_mroute_add_vif(ifp, ifaddr, flags)) { +		/* pim_mroute_add_vif reported error */ +		return -5; +	} -  pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; -  return 0; +	pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; +	return 0;  }  int pim_if_del_vif(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; +	struct pim_interface *pim_ifp = ifp->info; -  if (pim_ifp->mroute_vif_index < 1) { -    zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", -	      __PRETTY_FUNCTION__, -	      pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); -    return -1; -  } +	if (pim_ifp->mroute_vif_index < 1) { +		zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", +			  __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, +			  ifp->name, ifp->ifindex); +		return -1; +	} -  pim_mroute_del_vif(pim_ifp->mroute_vif_index); +	pim_mroute_del_vif(pim_ifp->mroute_vif_index); -  /* -    Update vif_index -   */ -  pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; +	/* +	  Update vif_index +	 */ +	pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; -  pim_ifp->mroute_vif_index = -1; +	pim_ifp->mroute_vif_index = -1; -  return 0; +	return 0;  }  void pim_if_add_vif_all()  { -  struct listnode  *ifnode; -  struct listnode  *ifnextnode; -  struct interface *ifp; +	struct listnode *ifnode; +	struct listnode *ifnextnode; +	struct interface *ifp; -  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { -    if (!ifp->info) -      continue; +	for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, +			       ifp)) { +		if (!ifp->info) +			continue; -    pim_if_add_vif(ifp); -  } +		pim_if_add_vif(ifp); +	}  }  void pim_if_del_vif_all()  { -  struct listnode  *ifnode; -  struct listnode  *ifnextnode; -  struct interface *ifp; +	struct listnode *ifnode; +	struct listnode *ifnextnode; +	struct interface *ifp; -  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { -    if (!ifp->info) -      continue; +	for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, +			       ifp)) { +		if (!ifp->info) +			continue; -    pim_if_del_vif(ifp); -  } +		pim_if_del_vif(ifp); +	}  }  struct interface *pim_if_find_by_vif_index(ifindex_t vif_index)  { -  struct listnode  *ifnode; -  struct interface *ifp; +	struct listnode *ifnode; +	struct interface *ifp; -  if (vif_index == 0) -    return if_lookup_by_name ("pimreg", VRF_DEFAULT); +	if (vif_index == 0) +		return if_lookup_by_name("pimreg", VRF_DEFAULT); -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { -    if (ifp->info) { -      struct pim_interface *pim_ifp; -      pim_ifp = ifp->info; +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { +		if (ifp->info) { +			struct pim_interface *pim_ifp; +			pim_ifp = ifp->info; -      if (vif_index == pim_ifp->mroute_vif_index) -	return ifp; -    } -  } +			if (vif_index == pim_ifp->mroute_vif_index) +				return ifp; +		} +	} -  return 0; +	return 0;  }  /* @@ -1091,69 +1104,67 @@ struct interface *pim_if_find_by_vif_index(ifindex_t vif_index)   */  int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex)  { -  struct pim_interface *pim_ifp; -  struct interface *ifp; +	struct pim_interface *pim_ifp; +	struct interface *ifp; -  ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); -  if (!ifp || !ifp->info) -    return -1; -  pim_ifp = ifp->info; +	ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); +	if (!ifp || !ifp->info) +		return -1; +	pim_ifp = ifp->info; -  return pim_ifp->mroute_vif_index; +	return pim_ifp->mroute_vif_index;  }  int pim_if_lan_delay_enabled(struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  pim_ifp = ifp->info; -  zassert(pim_ifp); -  zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); +	pim_ifp = ifp->info; +	zassert(pim_ifp); +	zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); -  return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; +	return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;  }  uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)  { -  if (pim_if_lan_delay_enabled(ifp)) { -    struct pim_interface *pim_ifp; -    pim_ifp = ifp->info; -    return pim_ifp->pim_neighbors_highest_propagation_delay_msec; -  } -  else { -    return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; -  } +	if (pim_if_lan_delay_enabled(ifp)) { +		struct pim_interface *pim_ifp; +		pim_ifp = ifp->info; +		return pim_ifp->pim_neighbors_highest_propagation_delay_msec; +	} else { +		return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; +	}  }  uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)  { -  if (pim_if_lan_delay_enabled(ifp)) { -    struct pim_interface *pim_ifp; -    pim_ifp = ifp->info; -    return pim_ifp->pim_neighbors_highest_override_interval_msec; -  } -  else { -    return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; -  } +	if (pim_if_lan_delay_enabled(ifp)) { +		struct pim_interface *pim_ifp; +		pim_ifp = ifp->info; +		return pim_ifp->pim_neighbors_highest_override_interval_msec; +	} else { +		return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; +	}  }  int pim_if_t_override_msec(struct interface *ifp)  { -  int effective_override_interval_msec; -  int t_override_msec; +	int effective_override_interval_msec; +	int t_override_msec; -  effective_override_interval_msec = -    pim_if_effective_override_interval_msec(ifp); +	effective_override_interval_msec = +		pim_if_effective_override_interval_msec(ifp); -  t_override_msec = random() % (effective_override_interval_msec + 1); +	t_override_msec = random() % (effective_override_interval_msec + 1); -  return t_override_msec; +	return t_override_msec;  }  uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)  { -  return pim_if_effective_propagation_delay_msec(ifp) + -    pim_if_effective_override_interval_msec(ifp); +	return pim_if_effective_propagation_delay_msec(ifp) +	       + pim_if_effective_override_interval_msec(ifp);  }  /* @@ -1168,294 +1179,303 @@ uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)  struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,  					  struct in_addr addr)  { -  struct listnode *neighnode; -  struct pim_neighbor *neigh; -  struct pim_interface *pim_ifp; -  struct prefix p; - -  zassert(ifp); - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__, -	      ifp->name); -    return 0; -  } - -  p.family = AF_INET; -  p.u.prefix4 = addr; -  p.prefixlen = IPV4_MAX_PREFIXLEN; - -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - -    /* primary address ? */ -    if (neigh->source_addr.s_addr == addr.s_addr) -      return neigh; - -    /* secondary address ? */ -    if (pim_neighbor_find_secondary(neigh, &p)) -	return neigh; -  } - -  if (PIM_DEBUG_PIM_TRACE) { -    char addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -    zlog_debug("%s: neighbor not found for address %s on interface %s", -	       __PRETTY_FUNCTION__,  -	       addr_str, ifp->name); -  } - -  return NULL; +	struct listnode *neighnode; +	struct pim_neighbor *neigh; +	struct pim_interface *pim_ifp; +	struct prefix p; + +	zassert(ifp); + +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		zlog_warn("%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ifp->name); +		return 0; +	} + +	p.family = AF_INET; +	p.u.prefix4 = addr; +	p.prefixlen = IPV4_MAX_PREFIXLEN; + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, +				  neigh)) { + +		/* primary address ? */ +		if (neigh->source_addr.s_addr == addr.s_addr) +			return neigh; + +		/* secondary address ? */ +		if (pim_neighbor_find_secondary(neigh, &p)) +			return neigh; +	} + +	if (PIM_DEBUG_PIM_TRACE) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_debug( +			"%s: neighbor not found for address %s on interface %s", +			__PRETTY_FUNCTION__, addr_str, ifp->name); +	} + +	return NULL;  }  long pim_if_t_suppressed_msec(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  long t_suppressed_msec; -  uint32_t ramount = 0; +	struct pim_interface *pim_ifp; +	long t_suppressed_msec; +	uint32_t ramount = 0; -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  /* join suppression disabled ? */ -  if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) -    return 0; +	/* join suppression disabled ? */ +	if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) +		return 0; -  /* t_suppressed = t_periodic * rand(1.1, 1.4) */ -  ramount = 1100 + (random() % (1400 - 1100 + 1)); -  t_suppressed_msec = qpim_t_periodic * ramount; +	/* t_suppressed = t_periodic * rand(1.1, 1.4) */ +	ramount = 1100 + (random() % (1400 - 1100 + 1)); +	t_suppressed_msec = qpim_t_periodic * ramount; -  return t_suppressed_msec; +	return t_suppressed_msec;  }  static void igmp_join_free(struct igmp_join *ij)  { -  XFREE(MTYPE_PIM_IGMP_JOIN, ij); +	XFREE(MTYPE_PIM_IGMP_JOIN, ij);  }  static struct igmp_join *igmp_join_find(struct list *join_list,  					struct in_addr group_addr,  					struct in_addr source_addr)  { -  struct listnode *node; -  struct igmp_join *ij; +	struct listnode *node; +	struct igmp_join *ij; -  zassert(join_list); +	zassert(join_list); -  for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { -    if ((group_addr.s_addr == ij->group_addr.s_addr) && -	(source_addr.s_addr == ij->source_addr.s_addr)) -      return ij; -  } +	for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { +		if ((group_addr.s_addr == ij->group_addr.s_addr) +		    && (source_addr.s_addr == ij->source_addr.s_addr)) +			return ij; +	} -  return 0; +	return 0;  } -static int igmp_join_sock(const char *ifname, -			  ifindex_t ifindex, -			  struct in_addr group_addr, -			  struct in_addr source_addr) +static int igmp_join_sock(const char *ifname, ifindex_t ifindex, +			  struct in_addr group_addr, struct in_addr source_addr)  { -  int join_fd; +	int join_fd; -  join_fd = pim_socket_raw(IPPROTO_IGMP); -  if (join_fd < 0) { -    return -1; -  } +	join_fd = pim_socket_raw(IPPROTO_IGMP); +	if (join_fd < 0) { +		return -1; +	} -  if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, ifname)) { -    close(join_fd); -    return -2; -  } +	if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, +				   ifname)) { +		close(join_fd); +		return -2; +	} -  return join_fd; +	return join_fd;  }  static struct igmp_join *igmp_join_new(struct interface *ifp,  				       struct in_addr group_addr,  				       struct in_addr source_addr)  { -  struct pim_interface *pim_ifp; -  struct igmp_join *ij; -  int join_fd; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr); -  if (join_fd < 0) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", -	      __PRETTY_FUNCTION__, -	      group_str, source_str, ifp->name); -    return 0; -  } - -  ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); -  if (!ij) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_err("%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", -	     __PRETTY_FUNCTION__, -	     sizeof(*ij), group_str, source_str, ifp->name); -    close(join_fd); -    return 0; -  } - -  ij->sock_fd       = join_fd; -  ij->group_addr    = group_addr; -  ij->source_addr   = source_addr; -  ij->sock_creation = pim_time_monotonic_sec(); - -  listnode_add(pim_ifp->igmp_join_list, ij); - -  return ij; +	struct pim_interface *pim_ifp; +	struct igmp_join *ij; +	int join_fd; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, +				 source_addr); +	if (join_fd < 0) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", +			__PRETTY_FUNCTION__, group_str, source_str, ifp->name); +		return 0; +	} + +	ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); +	if (!ij) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_err( +			"%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", +			__PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str, +			ifp->name); +		close(join_fd); +		return 0; +	} + +	ij->sock_fd = join_fd; +	ij->group_addr = group_addr; +	ij->source_addr = source_addr; +	ij->sock_creation = pim_time_monotonic_sec(); + +	listnode_add(pim_ifp->igmp_join_list, ij); + +	return ij;  } -int pim_if_igmp_join_add(struct interface *ifp, -			 struct in_addr group_addr, +int pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,  			 struct in_addr source_addr)  { -  struct pim_interface *pim_ifp; -  struct igmp_join *ij; - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__,  -	      ifp->name); -    return -1; -  } - -  if (!pim_ifp->igmp_join_list) { -    pim_ifp->igmp_join_list = list_new(); -    if (!pim_ifp->igmp_join_list) { -      zlog_err("%s %s: failure: igmp_join_list=list_new()", -	       __FILE__, __PRETTY_FUNCTION__); -      return -2; -    } -    pim_ifp->igmp_join_list->del = (void (*)(void *)) igmp_join_free; -  } - -  ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); -  if (ij) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: can't re-join existing IGMP group %s source %s on interface %s", -	      __PRETTY_FUNCTION__, -	      group_str, source_str, ifp->name); -    return -3; -  } - -  ij = igmp_join_new(ifp, group_addr, source_addr); -  if (!ij) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", -	      __PRETTY_FUNCTION__, -	      group_str, source_str, ifp->name); -    return -4; -  } - -  if (PIM_DEBUG_IGMP_EVENTS) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_debug("%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", -	      __PRETTY_FUNCTION__, -	      source_str, group_str, ifp->name); -  } - -  return 0; -} +	struct pim_interface *pim_ifp; +	struct igmp_join *ij; + +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		zlog_warn("%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ifp->name); +		return -1; +	} + +	if (!pim_ifp->igmp_join_list) { +		pim_ifp->igmp_join_list = list_new(); +		if (!pim_ifp->igmp_join_list) { +			zlog_err("%s %s: failure: igmp_join_list=list_new()", +				 __FILE__, __PRETTY_FUNCTION__); +			return -2; +		} +		pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free; +	} + +	ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); +	if (ij) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: can't re-join existing IGMP group %s source %s on interface %s", +			__PRETTY_FUNCTION__, group_str, source_str, ifp->name); +		return -3; +	} + +	ij = igmp_join_new(ifp, group_addr, source_addr); +	if (!ij) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", +			__PRETTY_FUNCTION__, group_str, source_str, ifp->name); +		return -4; +	} + +	if (PIM_DEBUG_IGMP_EVENTS) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_debug( +			"%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", +			__PRETTY_FUNCTION__, source_str, group_str, ifp->name); +	} +	return 0; +} -int pim_if_igmp_join_del(struct interface *ifp, -			 struct in_addr group_addr, +int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,  			 struct in_addr source_addr)  { -  struct pim_interface *pim_ifp; -  struct igmp_join *ij; - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__,  -	      ifp->name); -    return -1; -  } - -  if (!pim_ifp->igmp_join_list) { -    zlog_warn("%s: no IGMP join on interface %s", -	      __PRETTY_FUNCTION__,  -	      ifp->name); -    return -2; -  } - -  ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); -  if (!ij) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: could not find IGMP group %s source %s on interface %s", -	      __PRETTY_FUNCTION__, -	      group_str, source_str, ifp->name); -    return -3; -  } - -  if (close(ij->sock_fd)) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", -	      __PRETTY_FUNCTION__, -	      ij->sock_fd, group_str, source_str, ifp->name, errno, safe_strerror(errno)); -    /* warning only */ -  } -  listnode_delete(pim_ifp->igmp_join_list, ij); -  igmp_join_free(ij); -  if (listcount(pim_ifp->igmp_join_list) < 1) { -    list_delete(pim_ifp->igmp_join_list); -    pim_ifp->igmp_join_list = 0; -  } - -  return 0; +	struct pim_interface *pim_ifp; +	struct igmp_join *ij; + +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		zlog_warn("%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ifp->name); +		return -1; +	} + +	if (!pim_ifp->igmp_join_list) { +		zlog_warn("%s: no IGMP join on interface %s", +			  __PRETTY_FUNCTION__, ifp->name); +		return -2; +	} + +	ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); +	if (!ij) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: could not find IGMP group %s source %s on interface %s", +			__PRETTY_FUNCTION__, group_str, source_str, ifp->name); +		return -3; +	} + +	if (close(ij->sock_fd)) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", +			__PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str, +			ifp->name, errno, safe_strerror(errno)); +		/* warning only */ +	} +	listnode_delete(pim_ifp->igmp_join_list, ij); +	igmp_join_free(ij); +	if (listcount(pim_ifp->igmp_join_list) < 1) { +		list_delete(pim_ifp->igmp_join_list); +		pim_ifp->igmp_join_list = 0; +	} + +	return 0;  }  static void pim_if_igmp_join_del_all(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode *node; -  struct listnode *nextnode; -  struct igmp_join *ij; - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__,  -	      ifp->name); -    return; -  } - -  if (!pim_ifp->igmp_join_list) -    return; - -  for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) -    pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct listnode *nextnode; +	struct igmp_join *ij; + +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		zlog_warn("%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ifp->name); +		return; +	} + +	if (!pim_ifp->igmp_join_list) +		return; + +	for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) +		pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);  }  /* @@ -1475,63 +1495,66 @@ static void pim_if_igmp_join_del_all(struct interface *ifp)  void pim_if_assert_on_neighbor_down(struct interface *ifp,  				    struct in_addr neigh_addr)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct listnode      *next_node; -  struct pim_ifchannel *ch; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { -    /* Is (S,G,I) assert loser ? */ -    if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) -      continue; -    /* Dead neighbor was winner ? */ -    if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) -      continue; -     -    assert_action_a5(ch); -  } +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct listnode *next_node; +	struct pim_ifchannel *ch; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, +			       ch)) { +		/* Is (S,G,I) assert loser ? */ +		if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) +			continue; +		/* Dead neighbor was winner ? */ +		if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) +			continue; + +		assert_action_a5(ch); +	}  }  void pim_if_update_join_desired(struct pim_interface *pim_ifp)  { -  struct listnode      *ch_node; -  struct pim_ifchannel *ch; +	struct listnode *ch_node; +	struct pim_ifchannel *ch; -  /* clear off flag from interface's upstreams */ -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { -    PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(ch->upstream->flags); -  } +	/* clear off flag from interface's upstreams */ +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { +		PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED( +			ch->upstream->flags); +	} -  /* scan per-interface (S,G,I) state on this I interface */ -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { -    struct pim_upstream *up = ch->upstream; +	/* scan per-interface (S,G,I) state on this I interface */ +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { +		struct pim_upstream *up = ch->upstream; -    if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) -      continue; +		if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) +			continue; -    /* update join_desired for the global (S,G) state */ -    pim_upstream_update_join_desired(up); -    PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); -  } +		/* update join_desired for the global (S,G) state */ +		pim_upstream_update_join_desired(up); +		PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); +	}  }  void pim_if_update_assert_tracking_desired(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct listnode      *next_node; -  struct pim_ifchannel *ch; - -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return; - -  for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { -    pim_ifchannel_update_assert_tracking_desired(ch); -  } +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct listnode *next_node; +	struct pim_ifchannel *ch; + +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return; + +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, +			       ch)) { +		pim_ifchannel_update_assert_tracking_desired(ch); +	}  }  /* @@ -1539,52 +1562,48 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp)   * The pimreg is a special interface that we have that is not   * quite an inteface but a VIF is created for it.   */ -void pim_if_create_pimreg (void) +void pim_if_create_pimreg(void)  { -  if (!pim_regiface) { -    pim_regiface = if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); -    pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; +	if (!pim_regiface) { +		pim_regiface = +			if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); +		pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; -    pim_if_new(pim_regiface, 0, 0); -  } +		pim_if_new(pim_regiface, 0, 0); +	}  } -int -pim_if_connected_to_source (struct interface *ifp, struct in_addr src) +int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)  { -  struct listnode *cnode; -  struct connected *c; -  struct prefix p; - -  if (!ifp) -    return 0; - -  p.family = AF_INET; -  p.u.prefix4 = src; -  p.prefixlen = IPV4_MAX_BITLEN; - -  for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) -    { -      if ((c->address->family == AF_INET) && -         prefix_match (CONNECTED_PREFIX (c), &p)) -       { -         return 1; -       } -    } - -  return 0; +	struct listnode *cnode; +	struct connected *c; +	struct prefix p; + +	if (!ifp) +		return 0; + +	p.family = AF_INET; +	p.u.prefix4 = src; +	p.prefixlen = IPV4_MAX_BITLEN; + +	for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { +		if ((c->address->family == AF_INET) +		    && prefix_match(CONNECTED_PREFIX(c), &p)) { +			return 1; +		} +	} + +	return 0;  } -struct interface * -pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id) +struct interface *pim_if_lookup_address_vrf(struct in_addr src, vrf_id_t vrf_id)  { -  struct listnode *ifnode; -  struct interface *ifp; - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) -    { -      if (pim_if_connected_to_source (ifp, src) && ifp->info) -	return ifp; -    } -  return NULL; +	struct listnode *ifnode; +	struct interface *ifp; + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { +		if (pim_if_connected_to_source(ifp, src) && ifp->info) +			return ifp; +	} +	return NULL;  } diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index a1c2b692f4..e742e68f67 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -56,81 +56,86 @@  #define PIM_I_am_DR(pim_ifp) (pim_ifp)->pim_dr_addr.s_addr == (pim_ifp)->primary_address.s_addr  struct pim_iface_upstream_switch { -  struct in_addr address; -  struct list *us; +	struct in_addr address; +	struct list *us;  };  enum pim_secondary_addr_flags { -  PIM_SEC_ADDRF_NONE = 0, -  PIM_SEC_ADDRF_STALE = (1 << 0) +	PIM_SEC_ADDRF_NONE = 0, +	PIM_SEC_ADDRF_STALE = (1 << 0)  };  struct pim_secondary_addr { -  struct prefix addr; -  enum pim_secondary_addr_flags flags; +	struct prefix addr; +	enum pim_secondary_addr_flags flags;  };  struct pim_interface { -  uint32_t       options;                            /* bit vector */ -  ifindex_t      mroute_vif_index; -  struct in_addr primary_address; /* remember addr to detect change */ -  struct list    *sec_addr_list; /* list of struct pim_secondary_addr */ -  struct in_addr update_source;  /* user can statically set the primary -                                  * address of the interface */ - -  int          igmp_version;                                /* IGMP version */ -  int          igmp_default_robustness_variable;            /* IGMPv3 QRV */ -  int          igmp_default_query_interval;                 /* IGMPv3 secs between general queries */ -  int          igmp_query_max_response_time_dsec;           /* IGMPv3 Max Response Time in dsecs for general queries */ -  int          igmp_specific_query_max_response_time_dsec;  /* IGMPv3 Max Response Time in dsecs for specific queries */ -  struct list *igmp_socket_list;                            /* list of struct igmp_sock */ -  struct list *igmp_join_list;                              /* list of struct igmp_join */ - -  int            pim_sock_fd;       /* PIM socket file descriptor */ -  struct thread *t_pim_sock_read;   /* thread for reading PIM socket */ -  int64_t        pim_sock_creation; /* timestamp of PIM socket creation */ - -  struct thread *t_pim_hello_timer; -  int            pim_hello_period; -  int            pim_default_holdtime; -  int            pim_triggered_hello_delay; -  uint32_t       pim_generation_id; -  uint16_t       pim_propagation_delay_msec; /* config */ -  uint16_t       pim_override_interval_msec; /* config */ -  struct list   *pim_neighbor_list; /* list of struct pim_neighbor */ -  struct list   *upstream_switch_list; -  struct list   *pim_ifchannel_list; /* list of struct pim_ifchannel */ -  struct hash   *pim_ifchannel_hash; - -  /* neighbors without lan_delay */ -  int            pim_number_of_nonlandelay_neighbors; -  uint16_t       pim_neighbors_highest_propagation_delay_msec; -  uint16_t       pim_neighbors_highest_override_interval_msec; - -  /* DR Election */ -  int64_t        pim_dr_election_last; /* timestamp */ -  int            pim_dr_election_count; -  int            pim_dr_election_changes; -  struct in_addr pim_dr_addr; -  uint32_t       pim_dr_priority;            /* config */ -  int            pim_dr_num_nondrpri_neighbors; /* neighbors without dr_pri */ - -  int64_t        pim_ifstat_start; /* start timestamp for stats */ -  uint32_t       pim_ifstat_hello_sent; -  uint32_t       pim_ifstat_hello_sendfail; -  uint32_t       pim_ifstat_hello_recv; -  uint32_t       pim_ifstat_hello_recvfail; -  uint32_t       pim_ifstat_join_recv; -  uint32_t       pim_ifstat_join_send; -  uint32_t       pim_ifstat_prune_recv; -  uint32_t       pim_ifstat_prune_send; -  uint32_t       pim_ifstat_reg_recv; -  uint32_t       pim_ifstat_reg_send; -  uint32_t       pim_ifstat_reg_stop_recv; -  uint32_t       pim_ifstat_reg_stop_send; -  uint32_t       pim_ifstat_assert_recv; -  uint32_t       pim_ifstat_assert_send; -  struct bfd_info *bfd_info; +	uint32_t options; /* bit vector */ +	ifindex_t mroute_vif_index; +	struct in_addr primary_address; /* remember addr to detect change */ +	struct list *sec_addr_list;     /* list of struct pim_secondary_addr */ +	struct in_addr update_source;   /* user can statically set the primary +					 * address of the interface */ + +	int igmp_version;		      /* IGMP version */ +	int igmp_default_robustness_variable; /* IGMPv3 QRV */ +	int +		igmp_default_query_interval;   /* IGMPv3 secs between general +						  queries */ +	int igmp_query_max_response_time_dsec; /* IGMPv3 Max Response Time in +						  dsecs for general queries */ +	int igmp_specific_query_max_response_time_dsec; /* IGMPv3 Max Response +							   Time in dsecs for +							   specific queries */ +	struct list *igmp_socket_list; /* list of struct igmp_sock */ +	struct list *igmp_join_list;   /* list of struct igmp_join */ + +	int pim_sock_fd;		/* PIM socket file descriptor */ +	struct thread *t_pim_sock_read; /* thread for reading PIM socket */ +	int64_t pim_sock_creation;      /* timestamp of PIM socket creation */ + +	struct thread *t_pim_hello_timer; +	int pim_hello_period; +	int pim_default_holdtime; +	int pim_triggered_hello_delay; +	uint32_t pim_generation_id; +	uint16_t pim_propagation_delay_msec; /* config */ +	uint16_t pim_override_interval_msec; /* config */ +	struct list *pim_neighbor_list;      /* list of struct pim_neighbor */ +	struct list *upstream_switch_list; +	struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */ +	struct hash *pim_ifchannel_hash; + +	/* neighbors without lan_delay */ +	int pim_number_of_nonlandelay_neighbors; +	uint16_t pim_neighbors_highest_propagation_delay_msec; +	uint16_t pim_neighbors_highest_override_interval_msec; + +	/* DR Election */ +	int64_t pim_dr_election_last; /* timestamp */ +	int pim_dr_election_count; +	int pim_dr_election_changes; +	struct in_addr pim_dr_addr; +	uint32_t pim_dr_priority;	  /* config */ +	int pim_dr_num_nondrpri_neighbors; /* neighbors without dr_pri */ + +	int64_t pim_ifstat_start; /* start timestamp for stats */ +	uint32_t pim_ifstat_hello_sent; +	uint32_t pim_ifstat_hello_sendfail; +	uint32_t pim_ifstat_hello_recv; +	uint32_t pim_ifstat_hello_recvfail; +	uint32_t pim_ifstat_join_recv; +	uint32_t pim_ifstat_join_send; +	uint32_t pim_ifstat_prune_recv; +	uint32_t pim_ifstat_prune_send; +	uint32_t pim_ifstat_reg_recv; +	uint32_t pim_ifstat_reg_send; +	uint32_t pim_ifstat_reg_stop_recv; +	uint32_t pim_ifstat_reg_stop_send; +	uint32_t pim_ifstat_assert_recv; +	uint32_t pim_ifstat_assert_send; +	struct bfd_info *bfd_info;  };  extern struct interface *pim_regiface; @@ -139,16 +144,16 @@ extern struct list *pim_ifchannel_list;    if default_holdtime is set (>= 0), use it;    otherwise default_holdtime is 3.5 * hello_period   */ -#define PIM_IF_DEFAULT_HOLDTIME(pim_ifp) \ -  (((pim_ifp)->pim_default_holdtime < 0) ? \ -  ((pim_ifp)->pim_hello_period * 7 / 2) : \ -  ((pim_ifp)->pim_default_holdtime)) +#define PIM_IF_DEFAULT_HOLDTIME(pim_ifp)                                       \ +	(((pim_ifp)->pim_default_holdtime < 0)                                 \ +		 ? ((pim_ifp)->pim_hello_period * 7 / 2)                       \ +		 : ((pim_ifp)->pim_default_holdtime))  void pim_if_init(void); -void pim_if_terminate (void); +void pim_if_terminate(void);  struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim); -void                  pim_if_delete(struct interface *ifp); +void pim_if_delete(struct interface *ifp);  void pim_if_addr_add(struct connected *ifc);  void pim_if_addr_del(struct connected *ifc, int force_prim_as_any);  void pim_if_addr_add_all(struct interface *ifp); @@ -156,7 +161,8 @@ void pim_if_addr_del_all(struct interface *ifp);  void pim_if_addr_del_all_igmp(struct interface *ifp);  void pim_if_addr_del_all_pim(struct interface *ifp); -struct interface *pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id); +struct interface *pim_if_lookup_address_vrf(struct in_addr src, +					    vrf_id_t vrf_id);  int pim_if_add_vif(struct interface *ifp);  int pim_if_del_vif(struct interface *ifp); @@ -178,11 +184,9 @@ int pim_if_t_override_msec(struct interface *ifp);  struct in_addr pim_find_primary_addr(struct interface *ifp); -int pim_if_igmp_join_add(struct interface *ifp, -			 struct in_addr group_addr, +int pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,  			 struct in_addr source_addr); -int pim_if_igmp_join_del(struct interface *ifp, -			 struct in_addr group_addr, +int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,  			 struct in_addr source_addr);  void pim_if_update_could_assert(struct interface *ifp); @@ -199,7 +203,7 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp);  void pim_if_create_pimreg(void); -int pim_if_connected_to_source (struct interface *ifp, struct in_addr src); +int pim_if_connected_to_source(struct interface *ifp, struct in_addr src);  int pim_update_source_set(struct interface *ifp, struct in_addr source);  #endif /* PIM_IFACE_H */ diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 021722dfc2..d4916518e7 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -43,34 +43,33 @@  #include "pim_upstream.h"  #include "pim_ssm.h" -int -pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) +int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)  { -  struct pim_interface *pim_ifp1; -  struct pim_interface *pim_ifp2; +	struct pim_interface *pim_ifp1; +	struct pim_interface *pim_ifp2; -  pim_ifp1 = ch1->interface->info; -  pim_ifp2 = ch2->interface->info; +	pim_ifp1 = ch1->interface->info; +	pim_ifp2 = ch2->interface->info; -  if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) -    return -1; +	if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) +		return -1; -  if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) -    return 1; +	if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) +		return 1; -  if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) -    return -1; +	if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) +		return -1; -  if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) -    return 1; +	if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) +		return 1; -  if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) -    return -1; +	if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) +		return -1; -  if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) -    return 1; +	if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) +		return 1; -  return 0; +	return 0;  }  /* @@ -78,20 +77,18 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)   * remove the parent pointer from   * those pointing at us   */ -static void -pim_ifchannel_remove_children (struct pim_ifchannel *ch) +static void pim_ifchannel_remove_children(struct pim_ifchannel *ch)  { -  struct pim_ifchannel *child; +	struct pim_ifchannel *child; -  if (!ch->sources) -    return; +	if (!ch->sources) +		return; -  while (!list_isempty (ch->sources)) -    { -      child = listnode_head (ch->sources); -      child->parent = NULL; -      listnode_delete (ch->sources, child); -    } +	while (!list_isempty(ch->sources)) { +		child = listnode_head(ch->sources); +		child->parent = NULL; +		listnode_delete(ch->sources, child); +	}  }  /* @@ -99,284 +96,302 @@ pim_ifchannel_remove_children (struct pim_ifchannel *ch)   * find all the children that would point   * at us.   */ -static void -pim_ifchannel_find_new_children (struct pim_ifchannel *ch) +static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)  { -  struct pim_interface *pim_ifp = ch->interface->info; -  struct pim_ifchannel *child; -  struct listnode *ch_node; - -  // Basic Sanity that we are not being silly -  if ((ch->sg.src.s_addr != INADDR_ANY) && -      (ch->sg.grp.s_addr != INADDR_ANY)) -    return; - -  if ((ch->sg.src.s_addr == INADDR_ANY) && -      (ch->sg.grp.s_addr == INADDR_ANY)) -    return; - -  for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) -    { -      if ((ch->sg.grp.s_addr != INADDR_ANY) && -	  (child->sg.grp.s_addr == ch->sg.grp.s_addr) && -	  (child != ch)) -	{ -	  child->parent = ch; -	  listnode_add_sort (ch->sources, child); +	struct pim_interface *pim_ifp = ch->interface->info; +	struct pim_ifchannel *child; +	struct listnode *ch_node; + +	// Basic Sanity that we are not being silly +	if ((ch->sg.src.s_addr != INADDR_ANY) +	    && (ch->sg.grp.s_addr != INADDR_ANY)) +		return; + +	if ((ch->sg.src.s_addr == INADDR_ANY) +	    && (ch->sg.grp.s_addr == INADDR_ANY)) +		return; + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, +				  child)) { +		if ((ch->sg.grp.s_addr != INADDR_ANY) +		    && (child->sg.grp.s_addr == ch->sg.grp.s_addr) +		    && (child != ch)) { +			child->parent = ch; +			listnode_add_sort(ch->sources, child); +		}  	} -    }  }  void pim_ifchannel_free(struct pim_ifchannel *ch)  { -  XFREE(MTYPE_PIM_IFCHANNEL, ch); +	XFREE(MTYPE_PIM_IFCHANNEL, ch);  }  void pim_ifchannel_delete(struct pim_ifchannel *ch)  { -  struct pim_interface *pim_ifp; - -  pim_ifp = ch->interface->info; - -  if (ch->upstream->channel_oil) -    { -      uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; -      if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) -        mask = PIM_OIF_FLAG_PROTO_IGMP; - -      /* SGRpt entry could have empty oil */ -      if (ch->upstream->channel_oil) -        pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask); -      /* -       * Do we have any S,G's that are inheriting? -       * Nuke from on high too. -       */ -      if (ch->upstream->sources) -	{ -	  struct pim_upstream *child; -	  struct listnode *up_node; - -	  for (ALL_LIST_ELEMENTS_RO (ch->upstream->sources, up_node, child)) -            pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); +	struct pim_interface *pim_ifp; + +	pim_ifp = ch->interface->info; + +	if (ch->upstream->channel_oil) { +		uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; +		if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) +			mask = PIM_OIF_FLAG_PROTO_IGMP; + +		/* SGRpt entry could have empty oil */ +		if (ch->upstream->channel_oil) +			pim_channel_del_oif(ch->upstream->channel_oil, +					    ch->interface, mask); +		/* +		 * Do we have any S,G's that are inheriting? +		 * Nuke from on high too. +		 */ +		if (ch->upstream->sources) { +			struct pim_upstream *child; +			struct listnode *up_node; + +			for (ALL_LIST_ELEMENTS_RO(ch->upstream->sources, +						  up_node, child)) +				pim_channel_del_oif(child->channel_oil, +						    ch->interface, +						    PIM_OIF_FLAG_PROTO_STAR); +		} +	} + +	/* +	 * When this channel is removed +	 * we need to find all our children +	 * and make sure our pointers are fixed +	 */ +	pim_ifchannel_remove_children(ch); + +	if (ch->sources) +		list_delete(ch->sources); + +	listnode_delete(ch->upstream->ifchannels, ch); + +	if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { +		pim_upstream_update_join_desired(ch->upstream);  	} -    } - -  /* -   * When this channel is removed -   * we need to find all our children -   * and make sure our pointers are fixed -   */ -  pim_ifchannel_remove_children (ch); - -  if (ch->sources) -    list_delete (ch->sources); - -  listnode_delete(ch->upstream->ifchannels, ch); - -  if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { -    pim_upstream_update_join_desired(ch->upstream); -  } - -  /* upstream is common across ifchannels, check if upstream's -     ifchannel list is empty before deleting upstream_del -     ref count will take care of it. -  */ -  pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); -  ch->upstream = NULL; - -  THREAD_OFF(ch->t_ifjoin_expiry_timer); -  THREAD_OFF(ch->t_ifjoin_prune_pending_timer); -  THREAD_OFF(ch->t_ifassert_timer); - -  if (ch->parent) -    { -      listnode_delete (ch->parent->sources, ch); -      ch->parent = NULL; -    } -  /* -    notice that listnode_delete() can't be moved -    into pim_ifchannel_free() because the later is -    called by list_delete_all_node() -  */ -  listnode_delete(pim_ifp->pim_ifchannel_list, ch); -  hash_release(pim_ifp->pim_ifchannel_hash, ch); -  listnode_delete(pim_ifchannel_list, ch); - -  if (PIM_DEBUG_PIM_TRACE) -    zlog_debug ("%s: ifchannel entry %s is deleted ", __PRETTY_FUNCTION__, ch->sg_str); - -  pim_ifchannel_free(ch); + +	/* upstream is common across ifchannels, check if upstream's +	   ifchannel list is empty before deleting upstream_del +	   ref count will take care of it. +	*/ +	pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); +	ch->upstream = NULL; + +	THREAD_OFF(ch->t_ifjoin_expiry_timer); +	THREAD_OFF(ch->t_ifjoin_prune_pending_timer); +	THREAD_OFF(ch->t_ifassert_timer); + +	if (ch->parent) { +		listnode_delete(ch->parent->sources, ch); +		ch->parent = NULL; +	} +	/* +	  notice that listnode_delete() can't be moved +	  into pim_ifchannel_free() because the later is +	  called by list_delete_all_node() +	*/ +	listnode_delete(pim_ifp->pim_ifchannel_list, ch); +	hash_release(pim_ifp->pim_ifchannel_hash, ch); +	listnode_delete(pim_ifchannel_list, ch); + +	if (PIM_DEBUG_PIM_TRACE) +		zlog_debug("%s: ifchannel entry %s is deleted ", +			   __PRETTY_FUNCTION__, ch->sg_str); + +	pim_ifchannel_free(ch);  } -void -pim_ifchannel_delete_all (struct interface *ifp) +void pim_ifchannel_delete_all(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode *ifchannel_node; -  struct listnode *ifchannel_nextnode; -  struct pim_ifchannel *ifchannel; - -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return; - -  for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, ifchannel_node, -			  ifchannel_nextnode, ifchannel)) -    { -      pim_ifchannel_delete (ifchannel); -    } +	struct pim_interface *pim_ifp; +	struct listnode *ifchannel_node; +	struct listnode *ifchannel_nextnode; +	struct pim_ifchannel *ifchannel; + +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return; + +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, ifchannel_node, +			       ifchannel_nextnode, ifchannel)) { +		pim_ifchannel_delete(ifchannel); +	}  } -    +  static void delete_on_noinfo(struct pim_ifchannel *ch)  { -  if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO && -      ch->ifjoin_state == PIM_IFJOIN_NOINFO && -      ch->t_ifjoin_expiry_timer == NULL) -    pim_ifchannel_delete(ch); - +	if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO +	    && ch->ifjoin_state == PIM_IFJOIN_NOINFO +	    && ch->t_ifjoin_expiry_timer == NULL) +		pim_ifchannel_delete(ch);  } -void pim_ifchannel_ifjoin_switch(const char *caller, -				 struct pim_ifchannel *ch, +void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,  				 enum pim_ifjoin_state new_state)  { -  enum pim_ifjoin_state old_state = ch->ifjoin_state; - -  if (PIM_DEBUG_PIM_EVENTS) -    zlog_debug ("PIM_IFCHANNEL(%s): %s is switching from %s to %s", -		ch->interface->name, -		ch->sg_str, -		pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags), -		pim_ifchannel_ifjoin_name (new_state, 0)); - - -  if (old_state == new_state) { -    if (PIM_DEBUG_PIM_EVENTS) { -      zlog_debug("%s calledby %s: non-transition on state %d (%s)", -		 __PRETTY_FUNCTION__, caller, new_state, -		 pim_ifchannel_ifjoin_name(new_state, 0)); -    } -    return; -  } - -  ch->ifjoin_state = new_state; - -  if (ch->sg.src.s_addr == INADDR_ANY) -    { -      struct pim_upstream *up = ch->upstream; -      struct pim_upstream *child; -      struct listnode *up_node; - -      if (up) -	{ -	  if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) -	    { -	      for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) -		{ -		  struct channel_oil *c_oil = child->channel_oil; -		  struct pim_interface *pim_ifp = ch->interface->info; - -		  if (PIM_DEBUG_PIM_TRACE) -		    zlog_debug("%s %s: Prune(S,G)=%s from %s", -			       __FILE__, __PRETTY_FUNCTION__, -			       child->sg_str, up->sg_str); -		  if (!c_oil) -		    continue; - -		  if (!pim_upstream_evaluate_join_desired (child)) -                    { -                      pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); -                      pim_upstream_update_join_desired (child); -                    } - -		  /* -		   * If the S,G has no if channel and the c_oil still -		   * has output here then the *,G was supplying the implied -		   * if channel.  So remove it. -                   * I think this is dead code now. is it? -		   */ -		  if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) -                    pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); +	enum pim_ifjoin_state old_state = ch->ifjoin_state; + +	if (PIM_DEBUG_PIM_EVENTS) +		zlog_debug( +			"PIM_IFCHANNEL(%s): %s is switching from %s to %s", +			ch->interface->name, ch->sg_str, +			pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), +			pim_ifchannel_ifjoin_name(new_state, 0)); + + +	if (old_state == new_state) { +		if (PIM_DEBUG_PIM_EVENTS) { +			zlog_debug( +				"%s calledby %s: non-transition on state %d (%s)", +				__PRETTY_FUNCTION__, caller, new_state, +				pim_ifchannel_ifjoin_name(new_state, 0));  		} -	    } -	  if (ch->ifjoin_state == PIM_IFJOIN_JOIN) -	    { -	      for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) -		{ -		  if (PIM_DEBUG_PIM_TRACE) -		    zlog_debug("%s %s: Join(S,G)=%s from %s", -			       __FILE__, __PRETTY_FUNCTION__, -			       child->sg_str, up->sg_str); - -		  if (pim_upstream_evaluate_join_desired (child)) -		    { -                      pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); -                      pim_upstream_update_join_desired (child); -		    } +		return; +	} + +	ch->ifjoin_state = new_state; + +	if (ch->sg.src.s_addr == INADDR_ANY) { +		struct pim_upstream *up = ch->upstream; +		struct pim_upstream *child; +		struct listnode *up_node; + +		if (up) { +			if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) { +				for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, +							  child)) { +					struct channel_oil *c_oil = +						child->channel_oil; +					struct pim_interface *pim_ifp = +						ch->interface->info; + +					if (PIM_DEBUG_PIM_TRACE) +						zlog_debug( +							"%s %s: Prune(S,G)=%s from %s", +							__FILE__, +							__PRETTY_FUNCTION__, +							child->sg_str, +							up->sg_str); +					if (!c_oil) +						continue; + +					if (!pim_upstream_evaluate_join_desired( +						    child)) { +						pim_channel_del_oif( +							c_oil, ch->interface, +							PIM_OIF_FLAG_PROTO_STAR); +						pim_upstream_update_join_desired( +							child); +					} + +					/* +					 * If the S,G has no if channel and the +					 * c_oil still +					 * has output here then the *,G was +					 * supplying the implied +					 * if channel.  So remove it. +					 * I think this is dead code now. is it? +					 */ +					if (!ch +					    && c_oil->oil.mfcc_ttls +						       [pim_ifp->mroute_vif_index]) +						pim_channel_del_oif( +							c_oil, ch->interface, +							PIM_OIF_FLAG_PROTO_STAR); +				} +			} +			if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { +				for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, +							  child)) { +					if (PIM_DEBUG_PIM_TRACE) +						zlog_debug( +							"%s %s: Join(S,G)=%s from %s", +							__FILE__, +							__PRETTY_FUNCTION__, +							child->sg_str, +							up->sg_str); + +					if (pim_upstream_evaluate_join_desired( +						    child)) { +						pim_channel_add_oif( +							child->channel_oil, +							ch->interface, +							PIM_OIF_FLAG_PROTO_STAR); +						pim_upstream_update_join_desired( +							child); +					} +				} +			}  		} -	    }  	} -    } -  /* Transition to/from NOINFO ? */ -  if ((old_state == PIM_IFJOIN_NOINFO) || -      (new_state == PIM_IFJOIN_NOINFO)) { - -    if (PIM_DEBUG_PIM_EVENTS) { -      zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", -		 ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" : "UP"), -		 ch->sg_str, ch->interface->name); -    } - -    /* -      Record uptime of state transition to/from NOINFO -    */ -    ch->ifjoin_creation = pim_time_monotonic_sec(); - -    pim_upstream_update_join_desired(ch->upstream); -    pim_ifchannel_update_could_assert(ch); -    pim_ifchannel_update_assert_tracking_desired(ch); -  } +	/* Transition to/from NOINFO ? */ +	if ((old_state == PIM_IFJOIN_NOINFO) +	    || (new_state == PIM_IFJOIN_NOINFO)) { + +		if (PIM_DEBUG_PIM_EVENTS) { +			zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", +				   ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" +								     : "UP"), +				   ch->sg_str, ch->interface->name); +		} + +		/* +		  Record uptime of state transition to/from NOINFO +		*/ +		ch->ifjoin_creation = pim_time_monotonic_sec(); + +		pim_upstream_update_join_desired(ch->upstream); +		pim_ifchannel_update_could_assert(ch); +		pim_ifchannel_update_assert_tracking_desired(ch); +	}  }  const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, -                                      int flags) +				      int flags)  { -  switch (ifjoin_state) { -  case PIM_IFJOIN_NOINFO: -     if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) -       return "SGRpt"; -     else -       return "NOINFO"; -     break; -  case PIM_IFJOIN_JOIN: -     return "JOIN"; -     break; -  case PIM_IFJOIN_PRUNE: -     return "PRUNE"; -     break; -  case PIM_IFJOIN_PRUNE_PENDING: -     return "PRUNEP"; -     break; -  case PIM_IFJOIN_PRUNE_TMP: -     return "PRUNET"; -     break; -  case PIM_IFJOIN_PRUNE_PENDING_TMP: -     return "PRUNEPT"; -     break; -  } - -  return "ifjoin_bad_state"; +	switch (ifjoin_state) { +	case PIM_IFJOIN_NOINFO: +		if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) +			return "SGRpt"; +		else +			return "NOINFO"; +		break; +	case PIM_IFJOIN_JOIN: +		return "JOIN"; +		break; +	case PIM_IFJOIN_PRUNE: +		return "PRUNE"; +		break; +	case PIM_IFJOIN_PRUNE_PENDING: +		return "PRUNEP"; +		break; +	case PIM_IFJOIN_PRUNE_TMP: +		return "PRUNET"; +		break; +	case PIM_IFJOIN_PRUNE_PENDING_TMP: +		return "PRUNEPT"; +		break; +	} + +	return "ifjoin_bad_state";  }  const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state)  { -  switch (ifassert_state) { -  case PIM_IFASSERT_NOINFO:      return "NOINFO"; -  case PIM_IFASSERT_I_AM_WINNER: return "WINNER"; -  case PIM_IFASSERT_I_AM_LOSER:  return "LOSER"; -  } +	switch (ifassert_state) { +	case PIM_IFASSERT_NOINFO: +		return "NOINFO"; +	case PIM_IFASSERT_I_AM_WINNER: +		return "WINNER"; +	case PIM_IFASSERT_I_AM_LOSER: +		return "LOSER"; +	} -  return "ifassert_bad_state"; +	return "ifassert_bad_state";  }  /* @@ -387,88 +402,85 @@ const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state)  */  void reset_ifassert_state(struct pim_ifchannel *ch)  { -  struct in_addr any = { .s_addr = INADDR_ANY }; +	struct in_addr any = {.s_addr = INADDR_ANY}; -  THREAD_OFF(ch->t_ifassert_timer); +	THREAD_OFF(ch->t_ifassert_timer); -  pim_ifassert_winner_set(ch, -                          PIM_IFASSERT_NOINFO, -                          any, -                          qpim_infinite_assert_metric); +	pim_ifassert_winner_set(ch, PIM_IFASSERT_NOINFO, any, +				qpim_infinite_assert_metric);  }  struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,  					 struct prefix_sg *sg)  { -  struct pim_interface *pim_ifp; -  struct pim_ifchannel *ch; -  struct pim_ifchannel lookup; +	struct pim_interface *pim_ifp; +	struct pim_ifchannel *ch; +	struct pim_ifchannel lookup; -  pim_ifp = ifp->info; +	pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__, -	      pim_str_sg_dump (sg), -	      ifp->name); -    return NULL; -  } +	if (!pim_ifp) { +		zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); +		return NULL; +	} -  lookup.sg = *sg; -  ch = hash_lookup (pim_ifp->pim_ifchannel_hash, &lookup); +	lookup.sg = *sg; +	ch = hash_lookup(pim_ifp->pim_ifchannel_hash, &lookup); -  return ch; +	return ch;  }  static void ifmembership_set(struct pim_ifchannel *ch,  			     enum pim_ifmembership membership)  { -  if (ch->local_ifmembership == membership) -    return; - -  if (PIM_DEBUG_PIM_EVENTS) { -    zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", -	       __PRETTY_FUNCTION__, -	       ch->sg_str, -	       membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" : "NOINFO", -	       ch->interface->name); -  } -   -  ch->local_ifmembership = membership; - -  pim_upstream_update_join_desired(ch->upstream); -  pim_ifchannel_update_could_assert(ch); -  pim_ifchannel_update_assert_tracking_desired(ch); +	if (ch->local_ifmembership == membership) +		return; + +	if (PIM_DEBUG_PIM_EVENTS) { +		zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", +			   __PRETTY_FUNCTION__, ch->sg_str, +			   membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" +								  : "NOINFO", +			   ch->interface->name); +	} + +	ch->local_ifmembership = membership; + +	pim_upstream_update_join_desired(ch->upstream); +	pim_ifchannel_update_could_assert(ch); +	pim_ifchannel_update_assert_tracking_desired(ch);  }  void pim_ifchannel_membership_clear(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *ch_node; -  struct pim_ifchannel *ch; +	struct pim_interface *pim_ifp; +	struct listnode *ch_node; +	struct pim_ifchannel *ch; -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { -    ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); -  } +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { +		ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); +	}  }  void pim_ifchannel_delete_on_noinfo(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct listnode      *next_node; -  struct pim_ifchannel *ch; +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct listnode *next_node; +	struct pim_ifchannel *ch; -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { -    delete_on_noinfo(ch); -  } +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, +			       ch)) { +		delete_on_noinfo(ch); +	}  }  /* @@ -477,682 +489,687 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp)   * If we are passed a *,G, find the *,* ifchannel   * if we have it.   */ -static struct pim_ifchannel * -pim_ifchannel_find_parent (struct pim_ifchannel *ch) +static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch)  { -  struct prefix_sg parent_sg = ch->sg; -  struct pim_ifchannel *parent = NULL; - -  // (S,G) -  if ((parent_sg.src.s_addr != INADDR_ANY) && -      (parent_sg.grp.s_addr != INADDR_ANY)) -    { -      parent_sg.src.s_addr = INADDR_ANY; -      parent = pim_ifchannel_find (ch->interface, &parent_sg); - -      if (parent) -	listnode_add (parent->sources, ch); -      return parent; -    } - -  return NULL; +	struct prefix_sg parent_sg = ch->sg; +	struct pim_ifchannel *parent = NULL; + +	// (S,G) +	if ((parent_sg.src.s_addr != INADDR_ANY) +	    && (parent_sg.grp.s_addr != INADDR_ANY)) { +		parent_sg.src.s_addr = INADDR_ANY; +		parent = pim_ifchannel_find(ch->interface, &parent_sg); + +		if (parent) +			listnode_add(parent->sources, ch); +		return parent; +	} + +	return NULL;  } -struct pim_ifchannel * -pim_ifchannel_add(struct interface *ifp, -		  struct prefix_sg *sg, int flags) +struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, +					struct prefix_sg *sg, int flags)  { -  struct pim_interface *pim_ifp; -  struct pim_ifchannel *ch; -  struct pim_upstream *up; - -  ch = pim_ifchannel_find(ifp, sg); -  if (ch) -    return ch; - -  pim_ifp = ifp->info; - -  up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); -  if (!up) { -    zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", -	     __PRETTY_FUNCTION__, -	     pim_str_sg_dump (sg), ifp->name); -    return NULL; -  } - -  ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); -  if (!ch) { -    zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", -	      __PRETTY_FUNCTION__, -	      up->sg_str, ifp->name); - -    pim_upstream_del (up, __PRETTY_FUNCTION__); -    return NULL; -  } - -  ch->flags                        = 0; -  ch->upstream                     = up; -  ch->interface                    = ifp; -  ch->sg                           = *sg; -  pim_str_sg_set (sg, ch->sg_str); -  ch->parent                       = pim_ifchannel_find_parent (ch); -  if (ch->sg.src.s_addr == INADDR_ANY) -    { -      ch->sources = list_new (); -      ch->sources->cmp = (int (*)(void *, void *))pim_ifchannel_compare; -    } -  else -    ch->sources = NULL; - -  pim_ifchannel_find_new_children (ch); -  ch->local_ifmembership           = PIM_IFMEMBERSHIP_NOINFO; - -  ch->ifjoin_state                 = PIM_IFJOIN_NOINFO; -  ch->t_ifjoin_expiry_timer        = NULL; -  ch->t_ifjoin_prune_pending_timer = NULL; -  ch->ifjoin_creation              = 0; - -  ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); -  ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval (ch); - -  ch->ifassert_winner.s_addr = 0; - -  /* Assert state */ -  ch->t_ifassert_timer   = NULL; -  ch->ifassert_state = PIM_IFASSERT_NOINFO; -  reset_ifassert_state(ch); -  if (pim_macro_ch_could_assert_eval(ch)) -    PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); -  else -    PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - -  if (pim_macro_assert_tracking_desired_eval(ch)) -    PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); -  else -    PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - -  /* Attach to list */ -  listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); -  ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); -  listnode_add_sort(pim_ifchannel_list, ch); - -  listnode_add_sort(up->ifchannels, ch); - -  if (PIM_DEBUG_PIM_TRACE) -    zlog_debug ("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, ch->sg_str); - -  return ch; +	struct pim_interface *pim_ifp; +	struct pim_ifchannel *ch; +	struct pim_upstream *up; + +	ch = pim_ifchannel_find(ifp, sg); +	if (ch) +		return ch; + +	pim_ifp = ifp->info; + +	up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); +	if (!up) { +		zlog_err( +			"%s: could not attach upstream (S,G)=%s on interface %s", +			__PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); +		return NULL; +	} + +	ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); +	if (!ch) { +		zlog_warn( +			"%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", +			__PRETTY_FUNCTION__, up->sg_str, ifp->name); + +		pim_upstream_del(up, __PRETTY_FUNCTION__); +		return NULL; +	} + +	ch->flags = 0; +	ch->upstream = up; +	ch->interface = ifp; +	ch->sg = *sg; +	pim_str_sg_set(sg, ch->sg_str); +	ch->parent = pim_ifchannel_find_parent(ch); +	if (ch->sg.src.s_addr == INADDR_ANY) { +		ch->sources = list_new(); +		ch->sources->cmp = +			(int (*)(void *, void *))pim_ifchannel_compare; +	} else +		ch->sources = NULL; + +	pim_ifchannel_find_new_children(ch); +	ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; + +	ch->ifjoin_state = PIM_IFJOIN_NOINFO; +	ch->t_ifjoin_expiry_timer = NULL; +	ch->t_ifjoin_prune_pending_timer = NULL; +	ch->ifjoin_creation = 0; + +	ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); +	ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch); + +	ch->ifassert_winner.s_addr = 0; + +	/* Assert state */ +	ch->t_ifassert_timer = NULL; +	ch->ifassert_state = PIM_IFASSERT_NOINFO; +	reset_ifassert_state(ch); +	if (pim_macro_ch_could_assert_eval(ch)) +		PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); +	else +		PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + +	if (pim_macro_assert_tracking_desired_eval(ch)) +		PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); +	else +		PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + +	/* Attach to list */ +	listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); +	ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); +	listnode_add_sort(pim_ifchannel_list, ch); + +	listnode_add_sort(up->ifchannels, ch); + +	if (PIM_DEBUG_PIM_TRACE) +		zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, +			   ch->sg_str); + +	return ch;  }  static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del)  { -  pim_forward_stop(ch); -  pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); -  if (ch_del) -    delete_on_noinfo(ch); +	pim_forward_stop(ch); +	pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); +	if (ch_del) +		delete_on_noinfo(ch);  }  static int on_ifjoin_expiry_timer(struct thread *t)  { -  struct pim_ifchannel *ch; +	struct pim_ifchannel *ch; -  ch = THREAD_ARG(t); +	ch = THREAD_ARG(t); -  ifjoin_to_noinfo(ch, true); -  /* ch may have been deleted */ +	ifjoin_to_noinfo(ch, true); +	/* ch may have been deleted */ -  return 0; +	return 0;  }  static int on_ifjoin_prune_pending_timer(struct thread *t)  { -  struct pim_ifchannel *ch; -  int send_prune_echo; /* boolean */ -  struct interface *ifp; -  struct pim_interface *pim_ifp; - -  ch = THREAD_ARG(t); - -  if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) -    { -      /* Send PruneEcho(S,G) ? */ -      ifp = ch->interface; -      pim_ifp = ifp->info; -      send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); - -      if (send_prune_echo) -        { -          struct pim_rpf rpf; - -          rpf.source_nexthop.interface = ifp; -          rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; -          pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); -        } -      /* If SGRpt flag is set on ifchannel, Trigger SGRpt -         message on RP path upon prune timer expiry. -      */ -      if (PIM_IF_FLAG_TEST_S_G_RPT (ch->flags)) -        { -          if (ch->upstream) -            pim_upstream_update_join_desired(ch->upstream); -            /* -              ch->ifjoin_state transition to NOINFO state -              ch_del is set to 0 for not deleteing from here. -              Holdtime expiry (ch_del set to 1) delete the entry. -            */ -          ifjoin_to_noinfo(ch, false); -        } -      else -        ifjoin_to_noinfo(ch, true); -        /* from here ch may have been deleted */ -    } -  else -    { -      zlog_warn("%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", -		__PRETTY_FUNCTION__, pim_str_sg_dump (&ch->sg), -		pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags)); -    } - -  return 0; +	struct pim_ifchannel *ch; +	int send_prune_echo; /* boolean */ +	struct interface *ifp; +	struct pim_interface *pim_ifp; + +	ch = THREAD_ARG(t); + +	if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { +		/* Send PruneEcho(S,G) ? */ +		ifp = ch->interface; +		pim_ifp = ifp->info; +		send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); + +		if (send_prune_echo) { +			struct pim_rpf rpf; + +			rpf.source_nexthop.interface = ifp; +			rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; +			pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); +		} +		/* If SGRpt flag is set on ifchannel, Trigger SGRpt +		   message on RP path upon prune timer expiry. +		*/ +		if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { +			if (ch->upstream) +				pim_upstream_update_join_desired(ch->upstream); +			/* +			  ch->ifjoin_state transition to NOINFO state +			  ch_del is set to 0 for not deleteing from here. +			  Holdtime expiry (ch_del set to 1) delete the entry. +			*/ +			ifjoin_to_noinfo(ch, false); +		} else +			ifjoin_to_noinfo(ch, true); +		/* from here ch may have been deleted */ +	} else { +		zlog_warn( +			"%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", +			__PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg), +			pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); +	} + +	return 0;  } -static void check_recv_upstream(int is_join, -				struct interface *recv_ifp, -				struct in_addr upstream, -				struct prefix_sg *sg, -				uint8_t source_flags, -				int holdtime) +static void check_recv_upstream(int is_join, struct interface *recv_ifp, +				struct in_addr upstream, struct prefix_sg *sg, +				uint8_t source_flags, int holdtime)  { -  struct pim_upstream *up; - -  /* Upstream (S,G) in Joined state ? */ -  up = pim_upstream_find(sg); -  if (!up) -    return; -  if (up->join_state != PIM_UPSTREAM_JOINED) -    return; - -  /* Upstream (S,G) in Joined state */ - -  if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { -    /* RPF'(S,G) not found */ -    zlog_warn("%s %s: RPF'%s not found", -	      __FILE__, __PRETTY_FUNCTION__,  -	      up->sg_str); -    return; -  } - -  /* upstream directed to RPF'(S,G) ? */ -  if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { -    char up_str[INET_ADDRSTRLEN]; -    char rpf_str[PREFIX_STRLEN]; -    pim_inet4_dump("<up?>", upstream, up_str, sizeof(up_str)); -    pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); -    zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", -	      __FILE__, __PRETTY_FUNCTION__,  -	      up->sg_str, -	      up_str, rpf_str, recv_ifp->name); -    return; -  } -  /* upstream directed to RPF'(S,G) */ - -  if (is_join) { -    /* Join(S,G) to RPF'(S,G) */ -    pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, holdtime); -    return; -  } - -  /* Prune to RPF'(S,G) */ - -  if (source_flags & PIM_RPT_BIT_MASK) { -    if (source_flags & PIM_WILDCARD_BIT_MASK) { -      /* Prune(*,G) to RPF'(S,G) */ -      pim_upstream_join_timer_decrease_to_t_override("Prune(*,G)", up); -      return; -    } - -    /* Prune(S,G,rpt) to RPF'(S,G) */ -    pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", up); -    return; -  } - -  /* Prune(S,G) to RPF'(S,G) */ -  pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up); +	struct pim_upstream *up; + +	/* Upstream (S,G) in Joined state ? */ +	up = pim_upstream_find(sg); +	if (!up) +		return; +	if (up->join_state != PIM_UPSTREAM_JOINED) +		return; + +	/* Upstream (S,G) in Joined state */ + +	if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { +		/* RPF'(S,G) not found */ +		zlog_warn("%s %s: RPF'%s not found", __FILE__, +			  __PRETTY_FUNCTION__, up->sg_str); +		return; +	} + +	/* upstream directed to RPF'(S,G) ? */ +	if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { +		char up_str[INET_ADDRSTRLEN]; +		char rpf_str[PREFIX_STRLEN]; +		pim_inet4_dump("<up?>", upstream, up_str, sizeof(up_str)); +		pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, +			      sizeof(rpf_str)); +		zlog_warn( +			"%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", +			__FILE__, __PRETTY_FUNCTION__, up->sg_str, up_str, +			rpf_str, recv_ifp->name); +		return; +	} +	/* upstream directed to RPF'(S,G) */ + +	if (is_join) { +		/* Join(S,G) to RPF'(S,G) */ +		pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, +					   holdtime); +		return; +	} + +	/* Prune to RPF'(S,G) */ + +	if (source_flags & PIM_RPT_BIT_MASK) { +		if (source_flags & PIM_WILDCARD_BIT_MASK) { +			/* Prune(*,G) to RPF'(S,G) */ +			pim_upstream_join_timer_decrease_to_t_override( +				"Prune(*,G)", up); +			return; +		} + +		/* Prune(S,G,rpt) to RPF'(S,G) */ +		pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", +							       up); +		return; +	} + +	/* Prune(S,G) to RPF'(S,G) */ +	pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up);  } -static int -nonlocal_upstream(int is_join, -                  struct interface *recv_ifp, -                  struct in_addr upstream, -                  struct prefix_sg *sg, -                  uint8_t source_flags, -                  uint16_t holdtime) +static int nonlocal_upstream(int is_join, struct interface *recv_ifp, +			     struct in_addr upstream, struct prefix_sg *sg, +			     uint8_t source_flags, uint16_t holdtime)  { -  struct pim_interface *recv_pim_ifp; -  int is_local; /* boolean */ - -  recv_pim_ifp = recv_ifp->info; -  zassert(recv_pim_ifp); - -  is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); - -  if (is_local) -    return 0; - -  if (PIM_DEBUG_PIM_TRACE_DETAIL) { -    char up_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); -    zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", -              __PRETTY_FUNCTION__, -              is_join ? "join" : "prune", -              pim_str_sg_dump (sg), -              up_str, recv_ifp->name); -  } - -  /* -   * Since recv upstream addr was not directed to our primary -   * address, check if we should react to it in any way. -   */ -  check_recv_upstream(is_join, recv_ifp, upstream, sg, -                      source_flags, holdtime); - -  return 1; /* non-local */ +	struct pim_interface *recv_pim_ifp; +	int is_local; /* boolean */ + +	recv_pim_ifp = recv_ifp->info; +	zassert(recv_pim_ifp); + +	is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); + +	if (is_local) +		return 0; + +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		char up_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); +		zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", +			  __PRETTY_FUNCTION__, is_join ? "join" : "prune", +			  pim_str_sg_dump(sg), up_str, recv_ifp->name); +	} + +	/* +	 * Since recv upstream addr was not directed to our primary +	 * address, check if we should react to it in any way. +	 */ +	check_recv_upstream(is_join, recv_ifp, upstream, sg, source_flags, +			    holdtime); + +	return 1; /* non-local */  } -void pim_ifchannel_join_add(struct interface *ifp, -			    struct in_addr neigh_addr, -			    struct in_addr upstream, -			    struct prefix_sg *sg, -			    uint8_t source_flags, -			    uint16_t holdtime) +void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, +			    struct in_addr upstream, struct prefix_sg *sg, +			    uint8_t source_flags, uint16_t holdtime)  { -  struct pim_interface *pim_ifp; -  struct pim_ifchannel *ch; - -  if (nonlocal_upstream(1 /* join */, ifp, upstream, -			sg, source_flags, holdtime)) { -    return; -  } - -  ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); -  if (!ch) -    return; - -  /* -    RFC 4601: 4.6.1.  (S,G) Assert Message State Machine - -    Transitions from "I am Assert Loser" State - -    Receive Join(S,G) on Interface I - -    We receive a Join(S,G) that has the Upstream Neighbor Address -    field set to my primary IP address on interface I.  The action is -    to transition to NoInfo state, delete this (S,G) assert state -    (Actions A5 below), and allow the normal PIM Join/Prune mechanisms -    to operate. - -    Notice: The nonlocal_upstream() test above ensures the upstream -    address of the join message is our primary address. -   */ -  if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { -    char neigh_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, sizeof(neigh_str)); -    zlog_warn("%s: Assert Loser recv Join%s from %s on %s", -	      __PRETTY_FUNCTION__, -	      ch->sg_str, neigh_str, ifp->name); - -    assert_action_a5(ch); -  } - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  switch (ch->ifjoin_state) { -  case PIM_IFJOIN_NOINFO: -    pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); -    if (pim_macro_chisin_oiflist(ch)) { -      pim_upstream_inherited_olist (ch->upstream); -      pim_forward_start(ch); -    } -    /* -     * If we are going to be a LHR, we need to note it -     */ -    if (ch->upstream->parent && -        (ch->upstream->parent->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) && -        !(ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) -      { -        pim_upstream_ref (ch->upstream, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); -        pim_upstream_keep_alive_timer_start (ch->upstream, qpim_keep_alive_time); -      } -    break; -  case PIM_IFJOIN_JOIN: -    zassert(!ch->t_ifjoin_prune_pending_timer); - -    /* -      In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to a -      previously received join message with holdtime=0xFFFF. -     */ -    if (ch->t_ifjoin_expiry_timer) { -      unsigned long remain = -	thread_timer_remain_second(ch->t_ifjoin_expiry_timer); -      if (remain > holdtime) { +	struct pim_interface *pim_ifp; +	struct pim_ifchannel *ch; + +	if (nonlocal_upstream(1 /* join */, ifp, upstream, sg, source_flags, +			      holdtime)) { +		return; +	} + +	ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); +	if (!ch) +		return; +  	/* -	  RFC 4601: 4.5.3.  Receiving (S,G) Join/Prune Messages +	  RFC 4601: 4.6.1.  (S,G) Assert Message State Machine + +	  Transitions from "I am Assert Loser" State -	  Transitions from Join State +	  Receive Join(S,G) on Interface I -          The (S,G) downstream state machine on interface I remains in -          Join state, and the Expiry Timer (ET) is restarted, set to -          maximum of its current value and the HoldTime from the -          triggering Join/Prune message. +	  We receive a Join(S,G) that has the Upstream Neighbor Address +	  field set to my primary IP address on interface I.  The action is +	  to transition to NoInfo state, delete this (S,G) assert state +	  (Actions A5 below), and allow the normal PIM Join/Prune mechanisms +	  to operate. -	  Conclusion: Do not change the ET if the current value is -	  higher than the received join holdtime. +	  Notice: The nonlocal_upstream() test above ensures the upstream +	  address of the join message is our primary address.  	 */ -	return; -      } -    } -    THREAD_OFF(ch->t_ifjoin_expiry_timer); -    break; -  case PIM_IFJOIN_PRUNE: -    if (source_flags & PIM_ENCODE_RPT_BIT) -      pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); -    break; -  case PIM_IFJOIN_PRUNE_PENDING: -    THREAD_OFF(ch->t_ifjoin_prune_pending_timer); -    if (source_flags & PIM_ENCODE_RPT_BIT) -      { -	THREAD_OFF(ch->t_ifjoin_expiry_timer); -	pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); -      } -    else -      pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); -    break; -  case PIM_IFJOIN_PRUNE_TMP: -    break; -  case PIM_IFJOIN_PRUNE_PENDING_TMP: -    break; -  } - -  if (holdtime != 0xFFFF) { -    thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, -                     &ch->t_ifjoin_expiry_timer); -  } +	if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { +		char neigh_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, +			       sizeof(neigh_str)); +		zlog_warn("%s: Assert Loser recv Join%s from %s on %s", +			  __PRETTY_FUNCTION__, ch->sg_str, neigh_str, +			  ifp->name); + +		assert_action_a5(ch); +	} + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	switch (ch->ifjoin_state) { +	case PIM_IFJOIN_NOINFO: +		pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, +					    PIM_IFJOIN_JOIN); +		if (pim_macro_chisin_oiflist(ch)) { +			pim_upstream_inherited_olist(ch->upstream); +			pim_forward_start(ch); +		} +		/* +		 * If we are going to be a LHR, we need to note it +		 */ +		if (ch->upstream->parent && (ch->upstream->parent->flags +					     & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) +		    && !(ch->upstream->flags +			 & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) { +			pim_upstream_ref(ch->upstream, +					 PIM_UPSTREAM_FLAG_MASK_SRC_LHR, +					 __PRETTY_FUNCTION__); +			pim_upstream_keep_alive_timer_start( +				ch->upstream, qpim_keep_alive_time); +		} +		break; +	case PIM_IFJOIN_JOIN: +		zassert(!ch->t_ifjoin_prune_pending_timer); + +		/* +		  In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to +		  a +		  previously received join message with holdtime=0xFFFF. +		 */ +		if (ch->t_ifjoin_expiry_timer) { +			unsigned long remain = thread_timer_remain_second( +				ch->t_ifjoin_expiry_timer); +			if (remain > holdtime) { +				/* +				  RFC 4601: 4.5.3.  Receiving (S,G) Join/Prune +				  Messages + +				  Transitions from Join State + +				  The (S,G) downstream state machine on +				  interface I remains in +				  Join state, and the Expiry Timer (ET) is +				  restarted, set to +				  maximum of its current value and the HoldTime +				  from the +				  triggering Join/Prune message. + +				  Conclusion: Do not change the ET if the +				  current value is +				  higher than the received join holdtime. +				 */ +				return; +			} +		} +		THREAD_OFF(ch->t_ifjoin_expiry_timer); +		break; +	case PIM_IFJOIN_PRUNE: +		if (source_flags & PIM_ENCODE_RPT_BIT) +			pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, +						    PIM_IFJOIN_NOINFO); +		break; +	case PIM_IFJOIN_PRUNE_PENDING: +		THREAD_OFF(ch->t_ifjoin_prune_pending_timer); +		if (source_flags & PIM_ENCODE_RPT_BIT) { +			THREAD_OFF(ch->t_ifjoin_expiry_timer); +			pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, +						    PIM_IFJOIN_NOINFO); +		} else +			pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, +						    PIM_IFJOIN_JOIN); +		break; +	case PIM_IFJOIN_PRUNE_TMP: +		break; +	case PIM_IFJOIN_PRUNE_PENDING_TMP: +		break; +	} + +	if (holdtime != 0xFFFF) { +		thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, +				 &ch->t_ifjoin_expiry_timer); +	}  } -void pim_ifchannel_prune(struct interface *ifp, -			 struct in_addr upstream, -			 struct prefix_sg *sg, -			 uint8_t source_flags, +void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, +			 struct prefix_sg *sg, uint8_t source_flags,  			 uint16_t holdtime)  { -  struct pim_ifchannel *ch; -  struct pim_interface *pim_ifp; -  int jp_override_interval_msec; - -  if (nonlocal_upstream(0 /* prune */, ifp, upstream, -			sg, source_flags, holdtime)) { -    return; -  } - -  ch = pim_ifchannel_find (ifp, sg); -  if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug ("%s: Received prune with no relevant ifchannel %s(%s) state: %d", -		    __PRETTY_FUNCTION__, ifp->name, pim_str_sg_dump (sg), source_flags); -      return; -    } - -  ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); -  if (!ch) -    return; - -  pim_ifp = ifp->info; - -  switch (ch->ifjoin_state) { -  case PIM_IFJOIN_NOINFO: -    if (source_flags & PIM_ENCODE_RPT_BIT) -      { -	if (!(source_flags & PIM_ENCODE_WC_BIT)) -          PIM_IF_FLAG_SET_S_G_RPT(ch->flags); - -        ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; -        if (listcount(pim_ifp->pim_neighbor_list) > 1) -          jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); -        else -          jp_override_interval_msec = 0; /* schedule to expire immediately */ -          /* If we called ifjoin_prune() directly instead, care should -             be taken not to use "ch" afterwards since it would be -             deleted. */ +	struct pim_ifchannel *ch; +	struct pim_interface *pim_ifp; +	int jp_override_interval_msec; -	THREAD_OFF(ch->t_ifjoin_prune_pending_timer); -	THREAD_OFF(ch->t_ifjoin_expiry_timer); -	thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, -                              jp_override_interval_msec, -                              &ch->t_ifjoin_prune_pending_timer); -	thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, -                         &ch->t_ifjoin_expiry_timer); -        pim_upstream_update_join_desired(ch->upstream); -      } -    break; -  case PIM_IFJOIN_PRUNE_PENDING: -    /* nothing to do */ -    break; -  case PIM_IFJOIN_JOIN: -    THREAD_OFF(ch->t_ifjoin_expiry_timer); - -    pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_PRUNE_PENDING); - -    if (listcount(pim_ifp->pim_neighbor_list) > 1) -      jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); -    else -      jp_override_interval_msec = 0; /* schedule to expire immediately */ -      /* If we called ifjoin_prune() directly instead, care should -	 be taken not to use "ch" afterwards since it would be -	 deleted. */ -    THREAD_OFF(ch->t_ifjoin_prune_pending_timer); -    thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, -                          jp_override_interval_msec, -                          &ch->t_ifjoin_prune_pending_timer); -    break; -  case PIM_IFJOIN_PRUNE: -    if (source_flags & PIM_ENCODE_RPT_BIT) -      { -	THREAD_OFF(ch->t_ifjoin_prune_pending_timer); -	thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, -                         &ch->t_ifjoin_expiry_timer); -      } -    break; -  case PIM_IFJOIN_PRUNE_TMP: -    if (source_flags & PIM_ENCODE_RPT_BIT) -      { -	ch->ifjoin_state = PIM_IFJOIN_PRUNE; -	THREAD_OFF(ch->t_ifjoin_expiry_timer); -	thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, -                         &ch->t_ifjoin_expiry_timer); -      } -    break; -  case PIM_IFJOIN_PRUNE_PENDING_TMP: -    if (source_flags & PIM_ENCODE_RPT_BIT) -      { -	ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; -	THREAD_OFF(ch->t_ifjoin_expiry_timer); -	thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, -                         &ch->t_ifjoin_expiry_timer); -      } -    break; -  } +	if (nonlocal_upstream(0 /* prune */, ifp, upstream, sg, source_flags, +			      holdtime)) { +		return; +	} + +	ch = pim_ifchannel_find(ifp, sg); +	if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) { +		if (PIM_DEBUG_TRACE) +			zlog_debug( +				"%s: Received prune with no relevant ifchannel %s(%s) state: %d", +				__PRETTY_FUNCTION__, ifp->name, +				pim_str_sg_dump(sg), source_flags); +		return; +	} + +	ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); +	if (!ch) +		return; + +	pim_ifp = ifp->info; + +	switch (ch->ifjoin_state) { +	case PIM_IFJOIN_NOINFO: +		if (source_flags & PIM_ENCODE_RPT_BIT) { +			if (!(source_flags & PIM_ENCODE_WC_BIT)) +				PIM_IF_FLAG_SET_S_G_RPT(ch->flags); + +			ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; +			if (listcount(pim_ifp->pim_neighbor_list) > 1) +				jp_override_interval_msec = +					pim_if_jp_override_interval_msec(ifp); +			else +				jp_override_interval_msec = +					0; /* schedule to expire immediately */ +			/* If we called ifjoin_prune() directly instead, care +			   should +			   be taken not to use "ch" afterwards since it would be +			   deleted. */ + +			THREAD_OFF(ch->t_ifjoin_prune_pending_timer); +			THREAD_OFF(ch->t_ifjoin_expiry_timer); +			thread_add_timer_msec( +				master, on_ifjoin_prune_pending_timer, ch, +				jp_override_interval_msec, +				&ch->t_ifjoin_prune_pending_timer); +			thread_add_timer(master, on_ifjoin_expiry_timer, ch, +					 holdtime, &ch->t_ifjoin_expiry_timer); +			pim_upstream_update_join_desired(ch->upstream); +		} +		break; +	case PIM_IFJOIN_PRUNE_PENDING: +		/* nothing to do */ +		break; +	case PIM_IFJOIN_JOIN: +		THREAD_OFF(ch->t_ifjoin_expiry_timer); + +		pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, +					    PIM_IFJOIN_PRUNE_PENDING); + +		if (listcount(pim_ifp->pim_neighbor_list) > 1) +			jp_override_interval_msec = +				pim_if_jp_override_interval_msec(ifp); +		else +			jp_override_interval_msec = +				0; /* schedule to expire immediately */ +		/* If we called ifjoin_prune() directly instead, care should +		   be taken not to use "ch" afterwards since it would be +		   deleted. */ +		THREAD_OFF(ch->t_ifjoin_prune_pending_timer); +		thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, +				      jp_override_interval_msec, +				      &ch->t_ifjoin_prune_pending_timer); +		break; +	case PIM_IFJOIN_PRUNE: +		if (source_flags & PIM_ENCODE_RPT_BIT) { +			THREAD_OFF(ch->t_ifjoin_prune_pending_timer); +			thread_add_timer(master, on_ifjoin_expiry_timer, ch, +					 holdtime, &ch->t_ifjoin_expiry_timer); +		} +		break; +	case PIM_IFJOIN_PRUNE_TMP: +		if (source_flags & PIM_ENCODE_RPT_BIT) { +			ch->ifjoin_state = PIM_IFJOIN_PRUNE; +			THREAD_OFF(ch->t_ifjoin_expiry_timer); +			thread_add_timer(master, on_ifjoin_expiry_timer, ch, +					 holdtime, &ch->t_ifjoin_expiry_timer); +		} +		break; +	case PIM_IFJOIN_PRUNE_PENDING_TMP: +		if (source_flags & PIM_ENCODE_RPT_BIT) { +			ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; +			THREAD_OFF(ch->t_ifjoin_expiry_timer); +			thread_add_timer(master, on_ifjoin_expiry_timer, ch, +					 holdtime, &ch->t_ifjoin_expiry_timer); +		} +		break; +	}  } -int -pim_ifchannel_local_membership_add(struct interface *ifp, -				   struct prefix_sg *sg) +int pim_ifchannel_local_membership_add(struct interface *ifp, +				       struct prefix_sg *sg)  { -  struct pim_ifchannel *ch, *starch; -  struct pim_interface *pim_ifp; - -  /* PIM enabled on interface? */ -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return 0; -  if (!PIM_IF_TEST_PIM(pim_ifp->options)) -    return 0; - -  /* skip (*,G) ch creation if G is of type SSM */ -  if (sg->src.s_addr == INADDR_ANY) -    { -      if (pim_is_grp_ssm (sg->grp)) -        { -          if (PIM_DEBUG_PIM_EVENTS) -            zlog_debug("%s: local membership (S,G)=%s ignored as group is SSM", -                __PRETTY_FUNCTION__, pim_str_sg_dump (sg)); -          return 1; -        } -    } - -  ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); -  if (!ch) { -    return 0; -  } - -  ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); - -  if (sg->src.s_addr == INADDR_ANY) -    { -      struct pim_upstream *up = pim_upstream_find (sg); -      struct pim_upstream *child; -      struct listnode *up_node; - -      starch = ch; - -      for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) -        { -          if (PIM_DEBUG_EVENTS) -            zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", -                       __FILE__, __PRETTY_FUNCTION__, -                       child->sg_str, ifp->name, up->sg_str); - -          ch = pim_ifchannel_find (ifp, &child->sg); -          if (pim_upstream_evaluate_join_desired_interface (child, ch, starch)) -            { -              pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); -              pim_upstream_switch (child, PIM_UPSTREAM_JOINED); -            } -        } - -      if (pimg->spt.switchover == PIM_SPT_INFINITY) -        { -          if (pimg->spt.plist) -            { -              struct prefix_list *plist = prefix_list_lookup (AFI_IP, pimg->spt.plist); -              struct prefix g; -              g.family = AF_INET; -              g.prefixlen = IPV4_MAX_PREFIXLEN; -              g.u.prefix4 = up->sg.grp; - -              if (prefix_list_apply (plist, &g) == PREFIX_DENY) -                { -                  pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); -                } -            } -         } -       else -         pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); -    } - -  return 1; +	struct pim_ifchannel *ch, *starch; +	struct pim_interface *pim_ifp; + +	/* PIM enabled on interface? */ +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return 0; +	if (!PIM_IF_TEST_PIM(pim_ifp->options)) +		return 0; + +	/* skip (*,G) ch creation if G is of type SSM */ +	if (sg->src.s_addr == INADDR_ANY) { +		if (pim_is_grp_ssm(sg->grp)) { +			if (PIM_DEBUG_PIM_EVENTS) +				zlog_debug( +					"%s: local membership (S,G)=%s ignored as group is SSM", +					__PRETTY_FUNCTION__, +					pim_str_sg_dump(sg)); +			return 1; +		} +	} + +	ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); +	if (!ch) { +		return 0; +	} + +	ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); + +	if (sg->src.s_addr == INADDR_ANY) { +		struct pim_upstream *up = pim_upstream_find(sg); +		struct pim_upstream *child; +		struct listnode *up_node; + +		starch = ch; + +		for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { +			if (PIM_DEBUG_EVENTS) +				zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", +					   __FILE__, __PRETTY_FUNCTION__, +					   child->sg_str, ifp->name, +					   up->sg_str); + +			ch = pim_ifchannel_find(ifp, &child->sg); +			if (pim_upstream_evaluate_join_desired_interface( +				    child, ch, starch)) { +				pim_channel_add_oif(child->channel_oil, ifp, +						    PIM_OIF_FLAG_PROTO_STAR); +				pim_upstream_switch(child, PIM_UPSTREAM_JOINED); +			} +		} + +		if (pimg->spt.switchover == PIM_SPT_INFINITY) { +			if (pimg->spt.plist) { +				struct prefix_list *plist = prefix_list_lookup( +					AFI_IP, pimg->spt.plist); +				struct prefix g; +				g.family = AF_INET; +				g.prefixlen = IPV4_MAX_PREFIXLEN; +				g.u.prefix4 = up->sg.grp; + +				if (prefix_list_apply(plist, &g) +				    == PREFIX_DENY) { +					pim_channel_add_oif( +						up->channel_oil, pim_regiface, +						PIM_OIF_FLAG_PROTO_IGMP); +				} +			} +		} else +			pim_channel_add_oif(up->channel_oil, pim_regiface, +					    PIM_OIF_FLAG_PROTO_IGMP); +	} + +	return 1;  }  void pim_ifchannel_local_membership_del(struct interface *ifp,  					struct prefix_sg *sg)  { -  struct pim_ifchannel *starch, *ch, *orig; -  struct pim_interface *pim_ifp; - -  /* PIM enabled on interface? */ -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return; -  if (!PIM_IF_TEST_PIM(pim_ifp->options)) -    return; - -  orig = ch = pim_ifchannel_find(ifp, sg); -  if (!ch) -    return; - -  ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - -  if (sg->src.s_addr == INADDR_ANY) -    { -      struct pim_upstream *up = pim_upstream_find (sg); -      struct pim_upstream *child; -      struct listnode *up_node, *up_nnode; - -      starch = ch; - -      for (ALL_LIST_ELEMENTS (up->sources, up_node, up_nnode, child)) -        { -	  struct channel_oil *c_oil = child->channel_oil; -	  struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg); -	  struct pim_interface *pim_ifp = ifp->info; - -	  if (PIM_DEBUG_EVENTS) -	    zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", -		       __FILE__, __PRETTY_FUNCTION__, -		       up->sg_str, ifp->name, child->sg_str); - -          ch = pim_ifchannel_find (ifp, &child->sg); -	  if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch, starch)) -            pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - -	  /* -	   * If the S,G has no if channel and the c_oil still -	   * has output here then the *,G was supplying the implied -	   * if channel.  So remove it. -	   */ -	  if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) -            pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - -          /* Child node removal/ref count-- will happen as part of parent' delete_no_info */ -        } -    } -  delete_on_noinfo(orig); +	struct pim_ifchannel *starch, *ch, *orig; +	struct pim_interface *pim_ifp; + +	/* PIM enabled on interface? */ +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return; +	if (!PIM_IF_TEST_PIM(pim_ifp->options)) +		return; + +	orig = ch = pim_ifchannel_find(ifp, sg); +	if (!ch) +		return; + +	ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + +	if (sg->src.s_addr == INADDR_ANY) { +		struct pim_upstream *up = pim_upstream_find(sg); +		struct pim_upstream *child; +		struct listnode *up_node, *up_nnode; + +		starch = ch; + +		for (ALL_LIST_ELEMENTS(up->sources, up_node, up_nnode, child)) { +			struct channel_oil *c_oil = child->channel_oil; +			struct pim_ifchannel *chchannel = +				pim_ifchannel_find(ifp, &child->sg); +			struct pim_interface *pim_ifp = ifp->info; + +			if (PIM_DEBUG_EVENTS) +				zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", +					   __FILE__, __PRETTY_FUNCTION__, +					   up->sg_str, ifp->name, +					   child->sg_str); + +			ch = pim_ifchannel_find(ifp, &child->sg); +			if (c_oil +			    && !pim_upstream_evaluate_join_desired_interface( +				       child, ch, starch)) +				pim_channel_del_oif(c_oil, ifp, +						    PIM_OIF_FLAG_PROTO_STAR); + +			/* +			 * If the S,G has no if channel and the c_oil still +			 * has output here then the *,G was supplying the +			 * implied +			 * if channel.  So remove it. +			 */ +			if (!chchannel && c_oil +			    && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) +				pim_channel_del_oif(c_oil, ifp, +						    PIM_OIF_FLAG_PROTO_STAR); + +			/* Child node removal/ref count-- will happen as part of +			 * parent' delete_no_info */ +		} +	} +	delete_on_noinfo(orig);  }  void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch)  { -  int old_couldassert = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); -  int new_couldassert = PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); - -  if (new_couldassert == old_couldassert) -    return; - -  if (PIM_DEBUG_PIM_EVENTS) { -    char src_str[INET_ADDRSTRLEN]; -    char grp_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); -    zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", -	       __PRETTY_FUNCTION__, -	       src_str, grp_str, ch->interface->name, -	       old_couldassert, new_couldassert); -  } - -  if (new_couldassert) { -    /* CouldAssert(S,G,I) switched from FALSE to TRUE */ -    PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); -  } -  else { -    /* CouldAssert(S,G,I) switched from TRUE to FALSE */ -    PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - -    if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { -      assert_action_a4(ch); -    } -  } - -  pim_ifchannel_update_my_assert_metric(ch); +	int old_couldassert = +		PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); +	int new_couldassert = +		PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); + +	if (new_couldassert == old_couldassert) +		return; + +	if (PIM_DEBUG_PIM_EVENTS) { +		char src_str[INET_ADDRSTRLEN]; +		char grp_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); +		zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", +			   __PRETTY_FUNCTION__, src_str, grp_str, +			   ch->interface->name, old_couldassert, +			   new_couldassert); +	} + +	if (new_couldassert) { +		/* CouldAssert(S,G,I) switched from FALSE to TRUE */ +		PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); +	} else { +		/* CouldAssert(S,G,I) switched from TRUE to FALSE */ +		PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + +		if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { +			assert_action_a4(ch); +		} +	} + +	pim_ifchannel_update_my_assert_metric(ch);  }  /* @@ -1165,72 +1182,75 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch)   */  void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch)  { -  struct pim_assert_metric my_metric_new = pim_macro_ch_my_assert_metric_eval(ch); - -  if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) -      return; - -  if (PIM_DEBUG_PIM_EVENTS) { -    char src_str[INET_ADDRSTRLEN]; -    char grp_str[INET_ADDRSTRLEN]; -    char old_addr_str[INET_ADDRSTRLEN]; -    char new_addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); -    pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); -    pim_inet4_dump("<new_addr?>", my_metric_new.ip_address, new_addr_str, sizeof(new_addr_str)); -    zlog_debug("%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", -	       __PRETTY_FUNCTION__, -	       src_str, grp_str, ch->interface->name, -	       ch->ifassert_my_metric.rpt_bit_flag, -	       ch->ifassert_my_metric.metric_preference, -	       ch->ifassert_my_metric.route_metric, -	       old_addr_str, -	       my_metric_new.rpt_bit_flag, -	       my_metric_new.metric_preference, -	       my_metric_new.route_metric, -	       new_addr_str); -  } - -  ch->ifassert_my_metric = my_metric_new; - -  if (pim_assert_metric_better(&ch->ifassert_my_metric, -			       &ch->ifassert_winner_metric)) { -    assert_action_a5(ch); -  } +	struct pim_assert_metric my_metric_new = +		pim_macro_ch_my_assert_metric_eval(ch); + +	if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) +		return; + +	if (PIM_DEBUG_PIM_EVENTS) { +		char src_str[INET_ADDRSTRLEN]; +		char grp_str[INET_ADDRSTRLEN]; +		char old_addr_str[INET_ADDRSTRLEN]; +		char new_addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); +		pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address, +			       old_addr_str, sizeof(old_addr_str)); +		pim_inet4_dump("<new_addr?>", my_metric_new.ip_address, +			       new_addr_str, sizeof(new_addr_str)); +		zlog_debug( +			"%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", +			__PRETTY_FUNCTION__, src_str, grp_str, +			ch->interface->name, +			ch->ifassert_my_metric.rpt_bit_flag, +			ch->ifassert_my_metric.metric_preference, +			ch->ifassert_my_metric.route_metric, old_addr_str, +			my_metric_new.rpt_bit_flag, +			my_metric_new.metric_preference, +			my_metric_new.route_metric, new_addr_str); +	} + +	ch->ifassert_my_metric = my_metric_new; + +	if (pim_assert_metric_better(&ch->ifassert_my_metric, +				     &ch->ifassert_winner_metric)) { +		assert_action_a5(ch); +	}  }  void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch)  { -  int old_atd = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); -  int new_atd = PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); - -  if (new_atd == old_atd) -    return; - -  if (PIM_DEBUG_PIM_EVENTS) { -    char src_str[INET_ADDRSTRLEN]; -    char grp_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); -    pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); -    zlog_debug("%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", -	       __PRETTY_FUNCTION__, -	       src_str, grp_str, ch->interface->name, -	       old_atd, new_atd); -  } - -  if (new_atd) { -    /* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ -    PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); -  } -  else { -    /* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ -    PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - -    if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { -      assert_action_a5(ch); -    } -  } +	int old_atd = PIM_FORCE_BOOLEAN( +		PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); +	int new_atd = +		PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); + +	if (new_atd == old_atd) +		return; + +	if (PIM_DEBUG_PIM_EVENTS) { +		char src_str[INET_ADDRSTRLEN]; +		char grp_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); +		pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); +		zlog_debug( +			"%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", +			__PRETTY_FUNCTION__, src_str, grp_str, +			ch->interface->name, old_atd, new_atd); +	} + +	if (new_atd) { +		/* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ +		PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); +	} else { +		/* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ +		PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + +		if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { +			assert_action_a5(ch); +		} +	}  }  /* @@ -1239,36 +1259,34 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch)   * their upstream out that way and turn on forwarding   * for that ifchannel then.   */ -void -pim_ifchannel_scan_forward_start (struct interface *new_ifp) +void pim_ifchannel_scan_forward_start(struct interface *new_ifp)  { -  struct listnode *ifnode; -  struct interface *ifp; -  struct pim_interface *new_pim_ifp = new_ifp->info; - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) -    { -      struct pim_interface *loop_pim_ifp = ifp->info; -      struct listnode *ch_node; -      struct pim_ifchannel *ch; - -      if (!loop_pim_ifp) -        continue; - -      if (new_pim_ifp == loop_pim_ifp) -        continue; - -      for (ALL_LIST_ELEMENTS_RO (loop_pim_ifp->pim_ifchannel_list, ch_node, ch)) -        { -          if (ch->ifjoin_state == PIM_IFJOIN_JOIN) -            { -              struct pim_upstream *up = ch->upstream; -              if ((!up->channel_oil) && -		  (up->rpf.source_nexthop.interface == new_ifp)) -                pim_forward_start (ch); -            } -        } -    } +	struct listnode *ifnode; +	struct interface *ifp; +	struct pim_interface *new_pim_ifp = new_ifp->info; + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { +		struct pim_interface *loop_pim_ifp = ifp->info; +		struct listnode *ch_node; +		struct pim_ifchannel *ch; + +		if (!loop_pim_ifp) +			continue; + +		if (new_pim_ifp == loop_pim_ifp) +			continue; + +		for (ALL_LIST_ELEMENTS_RO(loop_pim_ifp->pim_ifchannel_list, +					  ch_node, ch)) { +			if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { +				struct pim_upstream *up = ch->upstream; +				if ((!up->channel_oil) +				    && (up->rpf.source_nexthop +						.interface == new_ifp)) +					pim_forward_start(ch); +			} +		} +	}  }  /* @@ -1278,87 +1296,89 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp)   * reception of a *,G join as well, when   * we get End of Message   */ -void -pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone) +void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, +					 uint8_t source_flags, uint8_t join, +					 uint8_t starg_alone)  { -  struct pim_ifchannel *child; -  struct listnode *ch_node; - -  if (PIM_DEBUG_PIM_TRACE) -    zlog_debug ("%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, -                pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), -                ch->sg_str, eom, join); -  if (!ch->sources) -    return; - -  for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child)) -    { -      /* Only *,G Join received and no (SG-RPT) prune. -         eom = 1, only (W,G) join_alone is true, WC and RPT are set. -         Scan all S,G associated to G and if any SG-RPT -         remove the SG-RPT flag. -      */ -      if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) && -          (source_flags & PIM_WILDCARD_BIT_MASK)) -        { -          if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) -            { -              struct pim_upstream *up = child->upstream; - -              PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); -              if (up) -                { -                  if (PIM_DEBUG_TRACE) -                    zlog_debug ("%s: SGRpt flag is cleared, add inherit oif to up %s", -                            __PRETTY_FUNCTION__, up->sg_str); -                  pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); -                  pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, child, PIM_IFJOIN_JOIN); -                } -            } -        } - -      if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) -        continue; - -      switch (child->ifjoin_state) -	{ -	case PIM_IFJOIN_NOINFO: -	case PIM_IFJOIN_JOIN: -	  break; -	case PIM_IFJOIN_PRUNE: -	  if (!eom) -	    child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; -	  break; -	case PIM_IFJOIN_PRUNE_PENDING: -	  if (!eom) -	    child->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING_TMP; -	  break; -	case PIM_IFJOIN_PRUNE_TMP: -	case PIM_IFJOIN_PRUNE_PENDING_TMP: -	  if (eom) -	    child->ifjoin_state = PIM_IFJOIN_NOINFO; -	  break; +	struct pim_ifchannel *child; +	struct listnode *ch_node; + +	if (PIM_DEBUG_PIM_TRACE) +		zlog_debug( +			"%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, +			pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), +			ch->sg_str, eom, join); +	if (!ch->sources) +		return; + +	for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) { +		/* Only *,G Join received and no (SG-RPT) prune. +		   eom = 1, only (W,G) join_alone is true, WC and RPT are set. +		   Scan all S,G associated to G and if any SG-RPT +		   remove the SG-RPT flag. +		*/ +		if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) +		    && (source_flags & PIM_WILDCARD_BIT_MASK)) { +			if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) { +				struct pim_upstream *up = child->upstream; + +				PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); +				if (up) { +					if (PIM_DEBUG_TRACE) +						zlog_debug( +							"%s: SGRpt flag is cleared, add inherit oif to up %s", +							__PRETTY_FUNCTION__, +							up->sg_str); +					pim_channel_add_oif( +						up->channel_oil, ch->interface, +						PIM_OIF_FLAG_PROTO_STAR); +					pim_ifchannel_ifjoin_switch( +						__PRETTY_FUNCTION__, child, +						PIM_IFJOIN_JOIN); +				} +			} +		} + +		if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) +			continue; + +		switch (child->ifjoin_state) { +		case PIM_IFJOIN_NOINFO: +		case PIM_IFJOIN_JOIN: +			break; +		case PIM_IFJOIN_PRUNE: +			if (!eom) +				child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; +			break; +		case PIM_IFJOIN_PRUNE_PENDING: +			if (!eom) +				child->ifjoin_state = +					PIM_IFJOIN_PRUNE_PENDING_TMP; +			break; +		case PIM_IFJOIN_PRUNE_TMP: +		case PIM_IFJOIN_PRUNE_PENDING_TMP: +			if (eom) +				child->ifjoin_state = PIM_IFJOIN_NOINFO; +			break; +		}  	} -    }  } -unsigned int -pim_ifchannel_hash_key (void *arg) +unsigned int pim_ifchannel_hash_key(void *arg)  { -  struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; +	struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; -  return jhash_2words (ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); +	return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0);  } -int -pim_ifchannel_equal (const void *arg1, const void *arg2) +int pim_ifchannel_equal(const void *arg1, const void *arg2)  { -  const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; -  const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; +	const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; +	const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; -  if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) && -      (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) -    return 1; +	if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) +	    && (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) +		return 1; -  return 0; +	return 0;  } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 455493a5bc..2260fd451b 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -28,31 +28,29 @@  struct pim_ifchannel;  #include "pim_upstream.h" -enum pim_ifmembership { -  PIM_IFMEMBERSHIP_NOINFO, -  PIM_IFMEMBERSHIP_INCLUDE -}; +enum pim_ifmembership { PIM_IFMEMBERSHIP_NOINFO, PIM_IFMEMBERSHIP_INCLUDE };  enum pim_ifjoin_state { -  PIM_IFJOIN_NOINFO, -  PIM_IFJOIN_JOIN, -  PIM_IFJOIN_PRUNE, -  PIM_IFJOIN_PRUNE_PENDING, -  PIM_IFJOIN_PRUNE_TMP, -  PIM_IFJOIN_PRUNE_PENDING_TMP, +	PIM_IFJOIN_NOINFO, +	PIM_IFJOIN_JOIN, +	PIM_IFJOIN_PRUNE, +	PIM_IFJOIN_PRUNE_PENDING, +	PIM_IFJOIN_PRUNE_TMP, +	PIM_IFJOIN_PRUNE_PENDING_TMP,  };  enum pim_ifassert_state { -  PIM_IFASSERT_NOINFO, -  PIM_IFASSERT_I_AM_WINNER, -  PIM_IFASSERT_I_AM_LOSER +	PIM_IFASSERT_NOINFO, +	PIM_IFASSERT_I_AM_WINNER, +	PIM_IFASSERT_I_AM_LOSER  };  struct pim_assert_metric { -  uint32_t       rpt_bit_flag; -  uint32_t       metric_preference; -  uint32_t       route_metric; -  struct in_addr ip_address; /* neighbor router that sourced the Assert message */ +	uint32_t rpt_bit_flag; +	uint32_t metric_preference; +	uint32_t route_metric; +	struct in_addr ip_address; /* neighbor router that sourced the Assert +				      message */  };  /* @@ -82,63 +80,58 @@ struct pim_assert_metric {    Per-interface (S,G) state  */  struct pim_ifchannel { -  struct pim_ifchannel     *parent; -  struct list              *sources; -  struct prefix_sg          sg; -  char                      sg_str[PIM_SG_LEN]; -  struct interface         *interface;   /* backpointer to interface */ -  uint32_t                  flags; - -  /* IGMPv3 determined interface has local members for (S,G) ? */ -  enum pim_ifmembership     local_ifmembership; - -  /* Per-interface (S,G) Join/Prune State (Section 4.1.4 of RFC4601) */ -  enum pim_ifjoin_state     ifjoin_state; -  struct thread            *t_ifjoin_expiry_timer; -  struct thread            *t_ifjoin_prune_pending_timer; -  int64_t                   ifjoin_creation; /* Record uptime of ifjoin state */ - -  /* Per-interface (S,G) Assert State (Section 4.6.1 of RFC4601) */ -  enum pim_ifassert_state   ifassert_state; -  struct thread            *t_ifassert_timer; -  struct in_addr            ifassert_winner; -  struct pim_assert_metric  ifassert_winner_metric; -  int64_t                   ifassert_creation; /* Record uptime of ifassert state */ -  struct pim_assert_metric  ifassert_my_metric; - -  /* Upstream (S,G) state */ -  struct pim_upstream      *upstream; +	struct pim_ifchannel *parent; +	struct list *sources; +	struct prefix_sg sg; +	char sg_str[PIM_SG_LEN]; +	struct interface *interface; /* backpointer to interface */ +	uint32_t flags; + +	/* IGMPv3 determined interface has local members for (S,G) ? */ +	enum pim_ifmembership local_ifmembership; + +	/* Per-interface (S,G) Join/Prune State (Section 4.1.4 of RFC4601) */ +	enum pim_ifjoin_state ifjoin_state; +	struct thread *t_ifjoin_expiry_timer; +	struct thread *t_ifjoin_prune_pending_timer; +	int64_t ifjoin_creation; /* Record uptime of ifjoin state */ + +	/* Per-interface (S,G) Assert State (Section 4.6.1 of RFC4601) */ +	enum pim_ifassert_state ifassert_state; +	struct thread *t_ifassert_timer; +	struct in_addr ifassert_winner; +	struct pim_assert_metric ifassert_winner_metric; +	int64_t ifassert_creation; /* Record uptime of ifassert state */ +	struct pim_assert_metric ifassert_my_metric; + +	/* Upstream (S,G) state */ +	struct pim_upstream *upstream;  };  void pim_ifchannel_free(struct pim_ifchannel *ch);  void pim_ifchannel_delete(struct pim_ifchannel *ch); -void pim_ifchannel_delete_all (struct interface *ifp); +void pim_ifchannel_delete_all(struct interface *ifp);  void pim_ifchannel_membership_clear(struct interface *ifp);  void pim_ifchannel_delete_on_noinfo(struct interface *ifp);  struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,  					 struct prefix_sg *sg);  struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,  					struct prefix_sg *sg, int flags); -void pim_ifchannel_join_add(struct interface *ifp, -			    struct in_addr neigh_addr, -			    struct in_addr upstream, -			    struct prefix_sg *sg, -			    uint8_t source_flags, -			    uint16_t holdtime); -void pim_ifchannel_prune(struct interface *ifp, -			 struct in_addr upstream, -			 struct prefix_sg *sg, -			 uint8_t source_flags, +void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, +			    struct in_addr upstream, struct prefix_sg *sg, +			    uint8_t source_flags, uint16_t holdtime); +void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, +			 struct prefix_sg *sg, uint8_t source_flags,  			 uint16_t holdtime);  int pim_ifchannel_local_membership_add(struct interface *ifp,  				       struct prefix_sg *sg);  void pim_ifchannel_local_membership_del(struct interface *ifp,  					struct prefix_sg *sg); -void pim_ifchannel_ifjoin_switch(const char *caller, -				 struct pim_ifchannel *ch, +void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,  				 enum pim_ifjoin_state new_state); -const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, int flags); +const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, +				      int flags);  const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state);  int pim_ifchannel_isin_oiflist(struct pim_ifchannel *ch); @@ -149,11 +142,13 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch);  void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch);  void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); -void pim_ifchannel_scan_forward_start (struct interface *new_ifp); -void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone); +void pim_ifchannel_scan_forward_start(struct interface *new_ifp); +void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, +					 uint8_t source_flags, uint8_t join, +					 uint8_t starg_alone); -int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); +int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); -unsigned int pim_ifchannel_hash_key (void *arg); -int pim_ifchannel_equal (const void *arg1, const void *arg2); +unsigned int pim_ifchannel_hash_key(void *arg); +int pim_ifchannel_equal(const void *arg1, const void *arg2);  #endif /* PIM_IFCHANNEL_H */ diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index ae5f365b82..c693f30ac2 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -43,62 +43,66 @@ static int pim_igmp_general_query(struct thread *t);  /* This socket is used for TXing IGMP packets only, IGMP RX happens   * in pim_mroute_msg()   */ -static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, uint32_t pim_options) +static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, +			  uint32_t pim_options)  { -  int fd; -  int join = 0; -  struct in_addr group; - -  fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifp, 1); - -  if (fd < 0) -    return -1; - -  if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { -    if (inet_aton(PIM_ALL_ROUTERS, &group)) { -      if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) -       ++join; -    } -    else { -      zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", -               __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), -               PIM_ALL_ROUTERS, errno, safe_strerror(errno)); -    } -  } - -  /* -    IGMP routers periodically send IGMP general queries to AllSystems=224.0.0.1 -    IGMP routers must receive general queries for querier election. -  */ -  if (inet_aton(PIM_ALL_SYSTEMS, &group)) { -    if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) -      ++join; -  } -  else { -    zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", -             __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), -             PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); -  } - -  if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) { -    if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) { -      ++join; -    } -  } -  else { -      zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", -               __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), -               PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); -  }     - -  if (!join) { -    zlog_err("IGMP socket fd=%d could not join any group on interface address %s", -            fd, inet_ntoa(ifaddr)); -    close(fd); -    fd = -1; -  } - -  return fd; +	int fd; +	int join = 0; +	struct in_addr group; + +	fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifp, 1); + +	if (fd < 0) +		return -1; + +	if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { +		if (inet_aton(PIM_ALL_ROUTERS, &group)) { +			if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) +				++join; +		} else { +			zlog_warn( +				"%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", +				__FILE__, __PRETTY_FUNCTION__, fd, +				inet_ntoa(ifaddr), PIM_ALL_ROUTERS, errno, +				safe_strerror(errno)); +		} +	} + +	/* +	  IGMP routers periodically send IGMP general queries to +	  AllSystems=224.0.0.1 +	  IGMP routers must receive general queries for querier election. +	*/ +	if (inet_aton(PIM_ALL_SYSTEMS, &group)) { +		if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) +			++join; +	} else { +		zlog_warn( +			"%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", +			__FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), +			PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); +	} + +	if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) { +		if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) { +			++join; +		} +	} else { +		zlog_warn( +			"%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", +			__FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), +			PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); +	} + +	if (!join) { +		zlog_err( +			"IGMP socket fd=%d could not join any group on interface address %s", +			fd, inet_ntoa(ifaddr)); +		close(fd); +		fd = -1; +	} + +	return fd;  }  #undef IGMP_SOCK_DUMP @@ -106,828 +110,834 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, uint32_t  #ifdef IGMP_SOCK_DUMP  static void igmp_sock_dump(array_t *igmp_sock_array)  { -  int size = array_size(igmp_sock_array); -  for (int i = 0; i < size; ++i) { -     -    struct igmp_sock *igmp = array_get(igmp_sock_array, i); -     -    zlog_debug("%s %s: [%d/%d] igmp_addr=%s fd=%d", -	       __FILE__, __PRETTY_FUNCTION__, -	       i, size, -	       inet_ntoa(igmp->ifaddr), -	       igmp->fd); -  } +	int size = array_size(igmp_sock_array); +	for (int i = 0; i < size; ++i) { + +		struct igmp_sock *igmp = array_get(igmp_sock_array, i); + +		zlog_debug("%s %s: [%d/%d] igmp_addr=%s fd=%d", __FILE__, +			   __PRETTY_FUNCTION__, i, size, +			   inet_ntoa(igmp->ifaddr), igmp->fd); +	}  }  #endif  struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,  					      struct in_addr ifaddr)  { -  struct listnode  *sock_node; -  struct igmp_sock *igmp; +	struct listnode *sock_node; +	struct igmp_sock *igmp;  #ifdef IGMP_SOCK_DUMP -  igmp_sock_dump(igmp_sock_list); +	igmp_sock_dump(igmp_sock_list);  #endif -  for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) -    if (ifaddr.s_addr == igmp->ifaddr.s_addr) -      return igmp; +	for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) +		if (ifaddr.s_addr == igmp->ifaddr.s_addr) +			return igmp; -  return 0; +	return 0;  } -struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, -					 int fd) +struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd)  { -  struct listnode  *sock_node; -  struct igmp_sock *igmp; +	struct listnode *sock_node; +	struct igmp_sock *igmp; -  for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) -    if (fd == igmp->fd) -      return igmp; +	for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) +		if (fd == igmp->fd) +			return igmp; -  return 0; +	return 0;  }  static int pim_igmp_other_querier_expire(struct thread *t)  { -  struct igmp_sock *igmp; - -  igmp = THREAD_ARG(t); - -  zassert(!igmp->t_igmp_query_timer); - -  if (PIM_DEBUG_IGMP_TRACE) { -    char ifaddr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -    zlog_debug("%s: Querier %s resuming", -	       __PRETTY_FUNCTION__, -	       ifaddr_str); -  } - -  /* -    We are the current querier, then -    re-start sending general queries. -    RFC 2236 - sec 7 Other Querier -    present timer expired (Send General -    Query, Set Gen. Query. timer) -  */ -  pim_igmp_general_query(t); - -  return 0; +	struct igmp_sock *igmp; + +	igmp = THREAD_ARG(t); + +	zassert(!igmp->t_igmp_query_timer); + +	if (PIM_DEBUG_IGMP_TRACE) { +		char ifaddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +			       sizeof(ifaddr_str)); +		zlog_debug("%s: Querier %s resuming", __PRETTY_FUNCTION__, +			   ifaddr_str); +	} + +	/* +	  We are the current querier, then +	  re-start sending general queries. +	  RFC 2236 - sec 7 Other Querier +	  present timer expired (Send General +	  Query, Set Gen. Query. timer) +	*/ +	pim_igmp_general_query(t); + +	return 0;  }  void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp)  { -  long other_querier_present_interval_msec; -  struct pim_interface *pim_ifp; - -  zassert(igmp); -  zassert(igmp->interface); -  zassert(igmp->interface->info); - -  pim_ifp = igmp->interface->info; - -  if (igmp->t_other_querier_timer) { -    /* -      There is other querier present already, -      then reset the other-querier-present timer. -    */ - -    if (PIM_DEBUG_IGMP_TRACE) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -      zlog_debug("Querier %s resetting TIMER event for Other-Querier-Present", -		 ifaddr_str); -    } -    THREAD_OFF(igmp->t_other_querier_timer); -  } -  else { -    /* -      We are the current querier, then stop sending general queries: -      igmp->t_igmp_query_timer = NULL; -    */ -    pim_igmp_general_query_off(igmp); -  } - -  /* -    Since this socket is starting the other-querier-present timer, -    there should not be periodic query timer for this socket. -   */ -  zassert(!igmp->t_igmp_query_timer); - -  /* -    RFC 3376: 8.5. Other Querier Present Interval - -    The Other Querier Present Interval is the length of time that must -    pass before a multicast router decides that there is no longer -    another multicast router which should be the querier.  This value -    MUST be ((the Robustness Variable) times (the Query Interval)) plus -    (one half of one Query Response Interval). - -    other_querier_present_interval_msec = \ -      igmp->querier_robustness_variable * \ -      1000 * igmp->querier_query_interval + \ -      100 * (pim_ifp->query_max_response_time_dsec >> 1); -  */ -  other_querier_present_interval_msec = -    PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, -		       igmp->querier_query_interval, -		       pim_ifp->igmp_query_max_response_time_dsec); -   -  if (PIM_DEBUG_IGMP_TRACE) { -    char ifaddr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -    zlog_debug("Querier %s scheduling %ld.%03ld sec TIMER event for Other-Querier-Present", -	       ifaddr_str, -	       other_querier_present_interval_msec / 1000, -	       other_querier_present_interval_msec % 1000); -  } -   -  thread_add_timer_msec(master, pim_igmp_other_querier_expire, igmp, -                        other_querier_present_interval_msec, -                        &igmp->t_other_querier_timer); +	long other_querier_present_interval_msec; +	struct pim_interface *pim_ifp; + +	zassert(igmp); +	zassert(igmp->interface); +	zassert(igmp->interface->info); + +	pim_ifp = igmp->interface->info; + +	if (igmp->t_other_querier_timer) { +		/* +		  There is other querier present already, +		  then reset the other-querier-present timer. +		*/ + +		if (PIM_DEBUG_IGMP_TRACE) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); +			zlog_debug( +				"Querier %s resetting TIMER event for Other-Querier-Present", +				ifaddr_str); +		} +		THREAD_OFF(igmp->t_other_querier_timer); +	} else { +		/* +		  We are the current querier, then stop sending general queries: +		  igmp->t_igmp_query_timer = NULL; +		*/ +		pim_igmp_general_query_off(igmp); +	} + +	/* +	  Since this socket is starting the other-querier-present timer, +	  there should not be periodic query timer for this socket. +	 */ +	zassert(!igmp->t_igmp_query_timer); + +	/* +	  RFC 3376: 8.5. Other Querier Present Interval + +	  The Other Querier Present Interval is the length of time that must +	  pass before a multicast router decides that there is no longer +	  another multicast router which should be the querier.  This value +	  MUST be ((the Robustness Variable) times (the Query Interval)) plus +	  (one half of one Query Response Interval). + +	  other_querier_present_interval_msec = \ +	    igmp->querier_robustness_variable * \ +	    1000 * igmp->querier_query_interval + \ +	    100 * (pim_ifp->query_max_response_time_dsec >> 1); +	*/ +	other_querier_present_interval_msec = PIM_IGMP_OQPI_MSEC( +		igmp->querier_robustness_variable, igmp->querier_query_interval, +		pim_ifp->igmp_query_max_response_time_dsec); + +	if (PIM_DEBUG_IGMP_TRACE) { +		char ifaddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +			       sizeof(ifaddr_str)); +		zlog_debug( +			"Querier %s scheduling %ld.%03ld sec TIMER event for Other-Querier-Present", +			ifaddr_str, other_querier_present_interval_msec / 1000, +			other_querier_present_interval_msec % 1000); +	} + +	thread_add_timer_msec(master, pim_igmp_other_querier_expire, igmp, +			      other_querier_present_interval_msec, +			      &igmp->t_other_querier_timer);  }  void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp)  { -  zassert(igmp); - -  if (PIM_DEBUG_IGMP_TRACE) { -    if (igmp->t_other_querier_timer) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -      zlog_debug("IGMP querier %s fd=%d cancelling other-querier-present TIMER event on %s", -		 ifaddr_str, igmp->fd, igmp->interface->name); -    } -  } -  THREAD_OFF(igmp->t_other_querier_timer); +	zassert(igmp); + +	if (PIM_DEBUG_IGMP_TRACE) { +		if (igmp->t_other_querier_timer) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); +			zlog_debug( +				"IGMP querier %s fd=%d cancelling other-querier-present TIMER event on %s", +				ifaddr_str, igmp->fd, igmp->interface->name); +		} +	} +	THREAD_OFF(igmp->t_other_querier_timer);  } -static int -igmp_recv_query(struct igmp_sock *igmp, int query_version, -                int max_resp_code, -                struct in_addr from, const char *from_str, -                char *igmp_msg, int igmp_msg_len) +static int igmp_recv_query(struct igmp_sock *igmp, int query_version, +			   int max_resp_code, struct in_addr from, +			   const char *from_str, char *igmp_msg, +			   int igmp_msg_len)  { -  struct interface     *ifp; -  struct pim_interface *pim_ifp; -  struct in_addr        group_addr; -  uint16_t              recv_checksum; -  uint16_t              checksum; - -  memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - -  ifp = igmp->interface; -  pim_ifp = ifp->info; - -  recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); - -  /* for computing checksum */ -  *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; - -  checksum = in_cksum(igmp_msg, igmp_msg_len); -  if (checksum != recv_checksum) { -    zlog_warn("Recv IGMP query v%d from %s on %s: checksum mismatch: received=%x computed=%x", -	      query_version, from_str, ifp->name, recv_checksum, checksum); -    return -1; -  } - -  /* RFC 3376 defines some guidelines on operating in backwards compatibility -   * with older versions of IGMP but there are some gaps in the logic: -   * -   * - once we drop from say version 3 to version 2 we will never go back to -   *   version 3 even if the node that TXed an IGMP v2 query upgrades to v3 -   * -   * - The node with the lowest IP is the querier so we will only know to drop -   *   from v3 to v2 if the node that is the querier is also the one that is -   *   running igmp v2.  If a non-querier only supports igmp v2 we will have -   *   no way of knowing. -   * -   * For now we will simplify things and inform the user that they need to -   * configure all PIM routers to use the same version of IGMP. -   */ -  if (query_version != pim_ifp->igmp_version) { -    zlog_warn("Recv IGMP query v%d from %s on %s but we are using v%d, please " -              "configure all PIM routers on this subnet to use the same " -              "IGMP version", -              query_version, from_str, ifp->name, pim_ifp->igmp_version); -    return 0; -  } - -  if (PIM_DEBUG_IGMP_PACKETS) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); -    zlog_debug("Recv IGMP query v%d from %s on %s for group %s", -	       query_version, from_str, ifp->name, group_str); -  } - -  /* -    RFC 3376: 6.6.2. Querier Election - -    When a router receives a query with a lower IP address, it sets -    the Other-Querier-Present timer to Other Querier Present Interval -    and ceases to send queries on the network if it was the previously -    elected querier. -   */ -  if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { - -    if (PIM_DEBUG_IGMP_TRACE) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -      zlog_debug("%s: local address %s (%u) lost querier election to %s (%u)", -		 ifp->name, -		 ifaddr_str, ntohl(igmp->ifaddr.s_addr), -		 from_str, ntohl(from.s_addr)); -    } - -    pim_igmp_other_querier_timer_on(igmp); -  } - -  /* IGMP version 3 is the only one where we process the RXed query */ -  if (query_version == 3) { -    igmp_v3_recv_query(igmp, from_str, igmp_msg); -  } - -  return 0; +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	struct in_addr group_addr; +	uint16_t recv_checksum; +	uint16_t checksum; + +	memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + +	ifp = igmp->interface; +	pim_ifp = ifp->info; + +	recv_checksum = *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET); + +	/* for computing checksum */ +	*(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; + +	checksum = in_cksum(igmp_msg, igmp_msg_len); +	if (checksum != recv_checksum) { +		zlog_warn( +			"Recv IGMP query v%d from %s on %s: checksum mismatch: received=%x computed=%x", +			query_version, from_str, ifp->name, recv_checksum, +			checksum); +		return -1; +	} + +	/* RFC 3376 defines some guidelines on operating in backwards +	 * compatibility +	 * with older versions of IGMP but there are some gaps in the logic: +	 * +	 * - once we drop from say version 3 to version 2 we will never go back +	 * to +	 *   version 3 even if the node that TXed an IGMP v2 query upgrades to +	 * v3 +	 * +	 * - The node with the lowest IP is the querier so we will only know to +	 * drop +	 *   from v3 to v2 if the node that is the querier is also the one that +	 * is +	 *   running igmp v2.  If a non-querier only supports igmp v2 we will +	 * have +	 *   no way of knowing. +	 * +	 * For now we will simplify things and inform the user that they need to +	 * configure all PIM routers to use the same version of IGMP. +	 */ +	if (query_version != pim_ifp->igmp_version) { +		zlog_warn( +			"Recv IGMP query v%d from %s on %s but we are using v%d, please " +			"configure all PIM routers on this subnet to use the same " +			"IGMP version", +			query_version, from_str, ifp->name, +			pim_ifp->igmp_version); +		return 0; +	} + +	if (PIM_DEBUG_IGMP_PACKETS) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("Recv IGMP query v%d from %s on %s for group %s", +			   query_version, from_str, ifp->name, group_str); +	} + +	/* +	  RFC 3376: 6.6.2. Querier Election + +	  When a router receives a query with a lower IP address, it sets +	  the Other-Querier-Present timer to Other Querier Present Interval +	  and ceases to send queries on the network if it was the previously +	  elected querier. +	 */ +	if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { + +		if (PIM_DEBUG_IGMP_TRACE) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); +			zlog_debug( +				"%s: local address %s (%u) lost querier election to %s (%u)", +				ifp->name, ifaddr_str, +				ntohl(igmp->ifaddr.s_addr), from_str, +				ntohl(from.s_addr)); +		} + +		pim_igmp_other_querier_timer_on(igmp); +	} + +	/* IGMP version 3 is the only one where we process the RXed query */ +	if (query_version == 3) { +		igmp_v3_recv_query(igmp, from_str, igmp_msg); +	} + +	return 0;  } -static void on_trace(const char *label, -		     struct interface *ifp, struct in_addr from) +static void on_trace(const char *label, struct interface *ifp, +		     struct in_addr from)  { -  if (PIM_DEBUG_IGMP_TRACE) { -    char from_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); -    zlog_debug("%s: from %s on %s", -	       label, from_str, ifp->name); -  } +	if (PIM_DEBUG_IGMP_TRACE) { +		char from_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); +		zlog_debug("%s: from %s on %s", label, from_str, ifp->name); +	}  } -static int -igmp_v1_recv_report (struct igmp_sock *igmp, -                     struct in_addr from, const char *from_str, -                     char *igmp_msg, int igmp_msg_len) +static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from, +			       const char *from_str, char *igmp_msg, +			       int igmp_msg_len)  { -  struct interface *ifp = igmp->interface; -  struct igmp_group *group; -  struct in_addr group_addr; +	struct interface *ifp = igmp->interface; +	struct igmp_group *group; +	struct in_addr group_addr; -  on_trace(__PRETTY_FUNCTION__, igmp->interface, from); +	on_trace(__PRETTY_FUNCTION__, igmp->interface, from); -  if (igmp_msg_len != IGMP_V12_MSG_SIZE) { -    zlog_warn("Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", -	      from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); -    return -1; -  } +	if (igmp_msg_len != IGMP_V12_MSG_SIZE) { +		zlog_warn( +			"Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", +			from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); +		return -1; +	} -  if (PIM_DEBUG_IGMP_TRACE) { -    zlog_warn("%s %s: FIXME WRITEME", -	      __FILE__, __PRETTY_FUNCTION__); -  } +	if (PIM_DEBUG_IGMP_TRACE) { +		zlog_warn("%s %s: FIXME WRITEME", __FILE__, +			  __PRETTY_FUNCTION__); +	} -  memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); +	memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); -  /* non-existant group is created as INCLUDE {empty} */ -  group = igmp_add_group_by_addr(igmp, group_addr); -  if (!group) { -    return -1; -  } +	/* non-existant group is created as INCLUDE {empty} */ +	group = igmp_add_group_by_addr(igmp, group_addr); +	if (!group) { +		return -1; +	} -  group->last_igmp_v1_report_dsec = pim_time_monotonic_dsec(); +	group->last_igmp_v1_report_dsec = pim_time_monotonic_dsec(); -  return 0; +	return 0;  }  int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)  { -  struct ip *ip_hdr; -  size_t ip_hlen; /* ip header length in bytes */ -  char *igmp_msg; -  int igmp_msg_len; -  int msg_type; -  char from_str[INET_ADDRSTRLEN]; -  char to_str[INET_ADDRSTRLEN]; -     -  if (len < sizeof(*ip_hdr)) { -    zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", -	      len, sizeof(*ip_hdr)); -    return -1; -  } - -  ip_hdr = (struct ip *) buf; - -  pim_inet4_dump("<src?>", ip_hdr->ip_src, from_str , sizeof(from_str)); -  pim_inet4_dump("<dst?>", ip_hdr->ip_dst, to_str , sizeof(to_str)); - -  ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - -  if (PIM_DEBUG_IGMP_PACKETS) { -    zlog_debug("Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d", -	       from_str, to_str, igmp->interface->name, len, ip_hlen, ip_hdr->ip_p); -  } - -  igmp_msg = buf + ip_hlen; -  msg_type = *igmp_msg; -  igmp_msg_len = len - ip_hlen; - -  if (PIM_DEBUG_IGMP_PACKETS) { -    zlog_debug("Recv IGMP packet from %s to %s on %s: ttl=%d msg_type=%d msg_size=%d", -	       from_str, to_str, igmp->interface->name, ip_hdr->ip_ttl, msg_type, -	       igmp_msg_len); -  } - -  if (igmp_msg_len < PIM_IGMP_MIN_LEN) { -    zlog_warn("IGMP message size=%d shorter than minimum=%d", -	      igmp_msg_len, PIM_IGMP_MIN_LEN); -    return -1; -  } - -  switch (msg_type) { -  case PIM_IGMP_MEMBERSHIP_QUERY: -    { -      int max_resp_code = igmp_msg[1]; -      int query_version; - -      /* -	RFC 3376: 7.1. Query Version Distinctions -	IGMPv1 Query: length = 8 octets AND Max Resp Code field is zero -	IGMPv2 Query: length = 8 octets AND Max Resp Code field is non-zero -	IGMPv3 Query: length >= 12 octets -      */ - -      if (igmp_msg_len == 8) { -	query_version = max_resp_code ? 2 : 1; -      } -      else if (igmp_msg_len >= 12) { -	query_version = 3; -      } -      else { -	zlog_warn("Unknown IGMP query version"); -	return -1; -      } +	struct ip *ip_hdr; +	size_t ip_hlen; /* ip header length in bytes */ +	char *igmp_msg; +	int igmp_msg_len; +	int msg_type; +	char from_str[INET_ADDRSTRLEN]; +	char to_str[INET_ADDRSTRLEN]; + +	if (len < sizeof(*ip_hdr)) { +		zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", len, +			  sizeof(*ip_hdr)); +		return -1; +	} + +	ip_hdr = (struct ip *)buf; + +	pim_inet4_dump("<src?>", ip_hdr->ip_src, from_str, sizeof(from_str)); +	pim_inet4_dump("<dst?>", ip_hdr->ip_dst, to_str, sizeof(to_str)); + +	ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ -      return igmp_recv_query(igmp, query_version, max_resp_code, -			     ip_hdr->ip_src, from_str, -			     igmp_msg, igmp_msg_len); -    } +	if (PIM_DEBUG_IGMP_PACKETS) { +		zlog_debug( +			"Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d", +			from_str, to_str, igmp->interface->name, len, ip_hlen, +			ip_hdr->ip_p); +	} + +	igmp_msg = buf + ip_hlen; +	msg_type = *igmp_msg; +	igmp_msg_len = len - ip_hlen; + +	if (PIM_DEBUG_IGMP_PACKETS) { +		zlog_debug( +			"Recv IGMP packet from %s to %s on %s: ttl=%d msg_type=%d msg_size=%d", +			from_str, to_str, igmp->interface->name, ip_hdr->ip_ttl, +			msg_type, igmp_msg_len); +	} -  case PIM_IGMP_V3_MEMBERSHIP_REPORT: -    return igmp_v3_recv_report(igmp, ip_hdr->ip_src, from_str, -                               igmp_msg, igmp_msg_len); +	if (igmp_msg_len < PIM_IGMP_MIN_LEN) { +		zlog_warn("IGMP message size=%d shorter than minimum=%d", +			  igmp_msg_len, PIM_IGMP_MIN_LEN); +		return -1; +	} + +	switch (msg_type) { +	case PIM_IGMP_MEMBERSHIP_QUERY: { +		int max_resp_code = igmp_msg[1]; +		int query_version; + +		/* +		  RFC 3376: 7.1. Query Version Distinctions +		  IGMPv1 Query: length = 8 octets AND Max Resp Code field is +		  zero +		  IGMPv2 Query: length = 8 octets AND Max Resp Code field is +		  non-zero +		  IGMPv3 Query: length >= 12 octets +		*/ + +		if (igmp_msg_len == 8) { +			query_version = max_resp_code ? 2 : 1; +		} else if (igmp_msg_len >= 12) { +			query_version = 3; +		} else { +			zlog_warn("Unknown IGMP query version"); +			return -1; +		} + +		return igmp_recv_query(igmp, query_version, max_resp_code, +				       ip_hdr->ip_src, from_str, igmp_msg, +				       igmp_msg_len); +	} -  case PIM_IGMP_V2_MEMBERSHIP_REPORT: -    return igmp_v2_recv_report(igmp, ip_hdr->ip_src, from_str, -                               igmp_msg, igmp_msg_len); +	case PIM_IGMP_V3_MEMBERSHIP_REPORT: +		return igmp_v3_recv_report(igmp, ip_hdr->ip_src, from_str, +					   igmp_msg, igmp_msg_len); -  case PIM_IGMP_V1_MEMBERSHIP_REPORT: -    return igmp_v1_recv_report(igmp, ip_hdr->ip_src, from_str, -                               igmp_msg, igmp_msg_len); +	case PIM_IGMP_V2_MEMBERSHIP_REPORT: +		return igmp_v2_recv_report(igmp, ip_hdr->ip_src, from_str, +					   igmp_msg, igmp_msg_len); -  case PIM_IGMP_V2_LEAVE_GROUP: -    return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, -                              igmp_msg, igmp_msg_len); -  } +	case PIM_IGMP_V1_MEMBERSHIP_REPORT: +		return igmp_v1_recv_report(igmp, ip_hdr->ip_src, from_str, +					   igmp_msg, igmp_msg_len); -  zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type); +	case PIM_IGMP_V2_LEAVE_GROUP: +		return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, +					  igmp_msg, igmp_msg_len); +	} -  return -1; +	zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type); + +	return -1;  }  void pim_igmp_general_query_on(struct igmp_sock *igmp)  { -  struct pim_interface *pim_ifp; -  int startup_mode; -  int query_interval; - -  /* -    Since this socket is starting as querier, -    there should not exist a timer for other-querier-present. -   */ -  zassert(!igmp->t_other_querier_timer); -  pim_ifp = igmp->interface->info; -  zassert(pim_ifp); - -  /* -    RFC 3376: 8.6. Startup Query Interval - -    The Startup Query Interval is the interval between General Queries -    sent by a Querier on startup.  Default: 1/4 the Query Interval. -    The first one should be sent out immediately instead of 125/4 -    seconds from now. -  */ -  startup_mode = igmp->startup_query_count > 0; -  if (startup_mode) { -    /* -     * If this is the first time we are sending a query on a -     * newly configured igmp interface send it out in 1 second -     * just to give the entire world a tiny bit of time to settle -     * else the query interval is: -     * query_interval = pim_ifp->igmp_default_query_interval >> 2; -     */ -    if (igmp->startup_query_count == igmp->querier_robustness_variable) -      query_interval = 1; -    else -      query_interval = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - -    --igmp->startup_query_count; -  } -  else { -    query_interval = igmp->querier_query_interval; -  } - -  if (PIM_DEBUG_IGMP_TRACE) { -    char ifaddr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -    zlog_debug("Querier %s scheduling %d-second (%s) TIMER event for IGMP query on fd=%d", -	       ifaddr_str, -	       query_interval, -	       startup_mode ? "startup" : "non-startup", -	       igmp->fd); -  } -  igmp->t_igmp_query_timer = NULL; -  thread_add_timer(master, pim_igmp_general_query, igmp, query_interval, -                   &igmp->t_igmp_query_timer); +	struct pim_interface *pim_ifp; +	int startup_mode; +	int query_interval; + +	/* +	  Since this socket is starting as querier, +	  there should not exist a timer for other-querier-present. +	 */ +	zassert(!igmp->t_other_querier_timer); +	pim_ifp = igmp->interface->info; +	zassert(pim_ifp); + +	/* +	  RFC 3376: 8.6. Startup Query Interval + +	  The Startup Query Interval is the interval between General Queries +	  sent by a Querier on startup.  Default: 1/4 the Query Interval. +	  The first one should be sent out immediately instead of 125/4 +	  seconds from now. +	*/ +	startup_mode = igmp->startup_query_count > 0; +	if (startup_mode) { +		/* +		 * If this is the first time we are sending a query on a +		 * newly configured igmp interface send it out in 1 second +		 * just to give the entire world a tiny bit of time to settle +		 * else the query interval is: +		 * query_interval = pim_ifp->igmp_default_query_interval >> 2; +		 */ +		if (igmp->startup_query_count +		    == igmp->querier_robustness_variable) +			query_interval = 1; +		else +			query_interval = PIM_IGMP_SQI( +				pim_ifp->igmp_default_query_interval); + +		--igmp->startup_query_count; +	} else { +		query_interval = igmp->querier_query_interval; +	} + +	if (PIM_DEBUG_IGMP_TRACE) { +		char ifaddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +			       sizeof(ifaddr_str)); +		zlog_debug( +			"Querier %s scheduling %d-second (%s) TIMER event for IGMP query on fd=%d", +			ifaddr_str, query_interval, +			startup_mode ? "startup" : "non-startup", igmp->fd); +	} +	igmp->t_igmp_query_timer = NULL; +	thread_add_timer(master, pim_igmp_general_query, igmp, query_interval, +			 &igmp->t_igmp_query_timer);  }  void pim_igmp_general_query_off(struct igmp_sock *igmp)  { -  zassert(igmp); - -  if (PIM_DEBUG_IGMP_TRACE) { -    if (igmp->t_igmp_query_timer) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -      zlog_debug("IGMP querier %s fd=%d cancelling query TIMER event on %s", -		 ifaddr_str, igmp->fd, igmp->interface->name); -    } -  } -  THREAD_OFF(igmp->t_igmp_query_timer); +	zassert(igmp); + +	if (PIM_DEBUG_IGMP_TRACE) { +		if (igmp->t_igmp_query_timer) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); +			zlog_debug( +				"IGMP querier %s fd=%d cancelling query TIMER event on %s", +				ifaddr_str, igmp->fd, igmp->interface->name); +		} +	} +	THREAD_OFF(igmp->t_igmp_query_timer);  }  /* Issue IGMP general query */  static int pim_igmp_general_query(struct thread *t)  { -  struct igmp_sock *igmp; -  struct in_addr dst_addr; -  struct in_addr group_addr; -  struct pim_interface *pim_ifp; -  int    query_buf_size; - -  igmp = THREAD_ARG(t); - -  zassert(igmp->interface); -  zassert(igmp->interface->info); - -  pim_ifp = igmp->interface->info; - -  if (pim_ifp->igmp_version == 3) { -    query_buf_size = PIM_IGMP_BUFSIZE_WRITE; -  } else { -    query_buf_size = IGMP_V12_MSG_SIZE; -  } - -  char query_buf[query_buf_size]; - -  /* -    RFC3376: 4.1.12. IP Destination Addresses for Queries - -    In IGMPv3, General Queries are sent with an IP destination address -    of 224.0.0.1, the all-systems multicast address.  Group-Specific -    and Group-and-Source-Specific Queries are sent with an IP -    destination address equal to the multicast address of interest. -  */ - -  dst_addr.s_addr   = htonl(INADDR_ALLHOSTS_GROUP); -  group_addr.s_addr = PIM_NET_INADDR_ANY; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char querier_str[INET_ADDRSTRLEN]; -    char dst_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<querier?>", igmp->ifaddr, querier_str, -		   sizeof(querier_str)); -    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); -    zlog_debug("Querier %s issuing IGMP general query to %s on %s", -	       querier_str, dst_str, igmp->interface->name); -  } - -  igmp_send_query (pim_ifp->igmp_version, -                   0 /* igmp_group */, -                   igmp->fd, -                   igmp->interface->name, -                   query_buf, -                   sizeof(query_buf), -                   0 /* num_sources */, -                   dst_addr, -                   group_addr, -                   pim_ifp->igmp_query_max_response_time_dsec, -                   1 /* s_flag: always set for general queries */, -                   igmp->querier_robustness_variable, -                   igmp->querier_query_interval); - -  pim_igmp_general_query_on(igmp); - -  return 0; +	struct igmp_sock *igmp; +	struct in_addr dst_addr; +	struct in_addr group_addr; +	struct pim_interface *pim_ifp; +	int query_buf_size; + +	igmp = THREAD_ARG(t); + +	zassert(igmp->interface); +	zassert(igmp->interface->info); + +	pim_ifp = igmp->interface->info; + +	if (pim_ifp->igmp_version == 3) { +		query_buf_size = PIM_IGMP_BUFSIZE_WRITE; +	} else { +		query_buf_size = IGMP_V12_MSG_SIZE; +	} + +	char query_buf[query_buf_size]; + +	/* +	  RFC3376: 4.1.12. IP Destination Addresses for Queries + +	  In IGMPv3, General Queries are sent with an IP destination address +	  of 224.0.0.1, the all-systems multicast address.  Group-Specific +	  and Group-and-Source-Specific Queries are sent with an IP +	  destination address equal to the multicast address of interest. +	*/ + +	dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); +	group_addr.s_addr = PIM_NET_INADDR_ANY; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char querier_str[INET_ADDRSTRLEN]; +		char dst_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<querier?>", igmp->ifaddr, querier_str, +			       sizeof(querier_str)); +		pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); +		zlog_debug("Querier %s issuing IGMP general query to %s on %s", +			   querier_str, dst_str, igmp->interface->name); +	} + +	igmp_send_query(pim_ifp->igmp_version, 0 /* igmp_group */, igmp->fd, +			igmp->interface->name, query_buf, sizeof(query_buf), +			0 /* num_sources */, dst_addr, group_addr, +			pim_ifp->igmp_query_max_response_time_dsec, +			1 /* s_flag: always set for general queries */, +			igmp->querier_robustness_variable, +			igmp->querier_query_interval); + +	pim_igmp_general_query_on(igmp); + +	return 0;  }  static void sock_close(struct igmp_sock *igmp)  { -  pim_igmp_other_querier_timer_off(igmp); -  pim_igmp_general_query_off(igmp); - -  if (PIM_DEBUG_IGMP_TRACE_DETAIL) { -    if (igmp->t_igmp_read) { -      zlog_debug("Cancelling READ event on IGMP socket %s fd=%d on interface %s", -		 inet_ntoa(igmp->ifaddr), igmp->fd, -		 igmp->interface->name); -    } -  } -  THREAD_OFF(igmp->t_igmp_read); -   -  if (close(igmp->fd)) { -    zlog_err("Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", -	     inet_ntoa(igmp->ifaddr), igmp->fd, igmp->interface->name, -	     errno, safe_strerror(errno)); -  } -   -  if (PIM_DEBUG_IGMP_TRACE_DETAIL) { -    zlog_debug("Deleted IGMP socket %s fd=%d on interface %s", -	       inet_ntoa(igmp->ifaddr), igmp->fd, igmp->interface->name); -  } +	pim_igmp_other_querier_timer_off(igmp); +	pim_igmp_general_query_off(igmp); + +	if (PIM_DEBUG_IGMP_TRACE_DETAIL) { +		if (igmp->t_igmp_read) { +			zlog_debug( +				"Cancelling READ event on IGMP socket %s fd=%d on interface %s", +				inet_ntoa(igmp->ifaddr), igmp->fd, +				igmp->interface->name); +		} +	} +	THREAD_OFF(igmp->t_igmp_read); + +	if (close(igmp->fd)) { +		zlog_err( +			"Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", +			inet_ntoa(igmp->ifaddr), igmp->fd, +			igmp->interface->name, errno, safe_strerror(errno)); +	} + +	if (PIM_DEBUG_IGMP_TRACE_DETAIL) { +		zlog_debug("Deleted IGMP socket %s fd=%d on interface %s", +			   inet_ntoa(igmp->ifaddr), igmp->fd, +			   igmp->interface->name); +	}  }  void igmp_startup_mode_on(struct igmp_sock *igmp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  pim_ifp = igmp->interface->info; +	pim_ifp = igmp->interface->info; -  /* -    RFC 3376: 8.7. Startup Query Count +	/* +	  RFC 3376: 8.7. Startup Query Count -    The Startup Query Count is the number of Queries sent out on -    startup, separated by the Startup Query Interval.  Default: the -    Robustness Variable. -  */ -  igmp->startup_query_count = igmp->querier_robustness_variable; +	  The Startup Query Count is the number of Queries sent out on +	  startup, separated by the Startup Query Interval.  Default: the +	  Robustness Variable. +	*/ +	igmp->startup_query_count = igmp->querier_robustness_variable; -  /* -    Since we're (re)starting, reset QQI to default Query Interval -  */ -  igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; +	/* +	  Since we're (re)starting, reset QQI to default Query Interval +	*/ +	igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;  }  static void igmp_group_free(struct igmp_group *group)  { -  list_free(group->group_source_list); +	list_free(group->group_source_list); -  XFREE(MTYPE_PIM_IGMP_GROUP, group); +	XFREE(MTYPE_PIM_IGMP_GROUP, group);  }  static void igmp_group_delete(struct igmp_group *group)  { -  struct listnode *src_node; -  struct listnode *src_nextnode; -  struct igmp_source *src; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("Deleting IGMP group %s from socket %d interface %s", -	       group_str, -	       group->group_igmp_sock->fd, -	       group->group_igmp_sock->interface->name); -  } - -  for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode, src)) { -    igmp_source_delete(src); -  } - -  if (group->t_group_query_retransmit_timer) { -    THREAD_OFF(group->t_group_query_retransmit_timer); -  } - -  group_timer_off(group); -  listnode_delete(group->group_igmp_sock->igmp_group_list, group); -  hash_release (group->group_igmp_sock->igmp_group_hash, group); - -  igmp_group_free(group); +	struct listnode *src_node; +	struct listnode *src_nextnode; +	struct igmp_source *src; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("Deleting IGMP group %s from socket %d interface %s", +			   group_str, group->group_igmp_sock->fd, +			   group->group_igmp_sock->interface->name); +	} + +	for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode, +			       src)) { +		igmp_source_delete(src); +	} + +	if (group->t_group_query_retransmit_timer) { +		THREAD_OFF(group->t_group_query_retransmit_timer); +	} + +	group_timer_off(group); +	listnode_delete(group->group_igmp_sock->igmp_group_list, group); +	hash_release(group->group_igmp_sock->igmp_group_hash, group); + +	igmp_group_free(group);  }  void igmp_group_delete_empty_include(struct igmp_group *group)  { -  zassert(!group->group_filtermode_isexcl); -  zassert(!listcount(group->group_source_list)); +	zassert(!group->group_filtermode_isexcl); +	zassert(!listcount(group->group_source_list)); -  igmp_group_delete(group); +	igmp_group_delete(group);  }  void igmp_sock_free(struct igmp_sock *igmp)  { -  zassert(!igmp->t_igmp_read); -  zassert(!igmp->t_igmp_query_timer); -  zassert(!igmp->t_other_querier_timer); -  zassert(igmp->igmp_group_list); -  zassert(!listcount(igmp->igmp_group_list)); +	zassert(!igmp->t_igmp_read); +	zassert(!igmp->t_igmp_query_timer); +	zassert(!igmp->t_other_querier_timer); +	zassert(igmp->igmp_group_list); +	zassert(!listcount(igmp->igmp_group_list)); -  list_free(igmp->igmp_group_list); -  hash_free(igmp->igmp_group_hash); +	list_free(igmp->igmp_group_list); +	hash_free(igmp->igmp_group_hash); -  XFREE(MTYPE_PIM_IGMP_SOCKET, igmp); +	XFREE(MTYPE_PIM_IGMP_SOCKET, igmp);  }  void igmp_sock_delete(struct igmp_sock *igmp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *grp_node; -  struct listnode      *grp_nextnode; -  struct igmp_group    *grp; - -  for (ALL_LIST_ELEMENTS(igmp->igmp_group_list, grp_node, grp_nextnode, grp)) { -    igmp_group_delete(grp); -  } +	struct pim_interface *pim_ifp; +	struct listnode *grp_node; +	struct listnode *grp_nextnode; +	struct igmp_group *grp; + +	for (ALL_LIST_ELEMENTS(igmp->igmp_group_list, grp_node, grp_nextnode, +			       grp)) { +		igmp_group_delete(grp); +	} -  sock_close(igmp); +	sock_close(igmp); -  pim_ifp = igmp->interface->info; +	pim_ifp = igmp->interface->info; -  listnode_delete(pim_ifp->igmp_socket_list, igmp); +	listnode_delete(pim_ifp->igmp_socket_list, igmp); -  igmp_sock_free(igmp); +	igmp_sock_free(igmp);  } -void -igmp_sock_delete_all (struct interface *ifp) +void igmp_sock_delete_all(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode *igmp_node, *igmp_nextnode; -  struct igmp_sock *igmp; +	struct pim_interface *pim_ifp; +	struct listnode *igmp_node, *igmp_nextnode; +	struct igmp_sock *igmp; -  pim_ifp = ifp->info; +	pim_ifp = ifp->info; -  for (ALL_LIST_ELEMENTS (pim_ifp->igmp_socket_list, igmp_node, -			  igmp_nextnode, igmp)) -    { -      igmp_sock_delete(igmp); -    } +	for (ALL_LIST_ELEMENTS(pim_ifp->igmp_socket_list, igmp_node, +			       igmp_nextnode, igmp)) { +		igmp_sock_delete(igmp); +	}  } -static unsigned int -igmp_group_hash_key (void *arg) +static unsigned int igmp_group_hash_key(void *arg)  { -  struct igmp_group *group = (struct igmp_group *)arg; +	struct igmp_group *group = (struct igmp_group *)arg; -  return jhash_1word(group->group_addr.s_addr, 0); +	return jhash_1word(group->group_addr.s_addr, 0);  } -static int -igmp_group_hash_equal (const void *arg1, const void *arg2) +static int igmp_group_hash_equal(const void *arg1, const void *arg2)  { -  const struct igmp_group *g1 = (const struct igmp_group *)arg1; -  const struct igmp_group *g2 = (const struct igmp_group *)arg2; +	const struct igmp_group *g1 = (const struct igmp_group *)arg1; +	const struct igmp_group *g2 = (const struct igmp_group *)arg2; -  if (g1->group_addr.s_addr == g2->group_addr.s_addr) -    return 1; +	if (g1->group_addr.s_addr == g2->group_addr.s_addr) +		return 1; -  return 0; +	return 0;  } -static struct igmp_sock *igmp_sock_new(int fd, -				       struct in_addr ifaddr, +static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,  				       struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct igmp_sock *igmp; - -  pim_ifp = ifp->info; - -  if (PIM_DEBUG_IGMP_TRACE) { -    zlog_debug("Creating IGMP socket fd=%d for address %s on interface %s", -	       fd, inet_ntoa(ifaddr), ifp->name); -  } - -  igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); -  if (!igmp) { -    zlog_warn("%s %s: XCALLOC() failure", -              __FILE__, __PRETTY_FUNCTION__); -    return 0; -  } - -  igmp->igmp_group_list = list_new(); -  if (!igmp->igmp_group_list) { -    zlog_err("%s %s: failure: igmp_group_list = list_new()", -	     __FILE__, __PRETTY_FUNCTION__); -    return 0; -  } -  igmp->igmp_group_list->del = (void (*)(void *)) igmp_group_free; - -  igmp->igmp_group_hash = hash_create (igmp_group_hash_key, -                                       igmp_group_hash_equal, NULL); - -  igmp->fd                          = fd; -  igmp->interface                   = ifp; -  igmp->ifaddr                      = ifaddr; -  igmp->t_igmp_read                 = NULL; -  igmp->t_igmp_query_timer          = NULL; -  igmp->t_other_querier_timer       = NULL; /* no other querier present */ -  igmp->querier_robustness_variable = pim_ifp->igmp_default_robustness_variable; -  igmp->sock_creation               = pim_time_monotonic_sec(); - -  /* -    igmp_startup_mode_on() will reset QQI: - -    igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; -  */ -  igmp_startup_mode_on(igmp); -  pim_igmp_general_query_on(igmp); - -  return igmp; +	struct pim_interface *pim_ifp; +	struct igmp_sock *igmp; + +	pim_ifp = ifp->info; + +	if (PIM_DEBUG_IGMP_TRACE) { +		zlog_debug( +			"Creating IGMP socket fd=%d for address %s on interface %s", +			fd, inet_ntoa(ifaddr), ifp->name); +	} + +	igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); +	if (!igmp) { +		zlog_warn("%s %s: XCALLOC() failure", __FILE__, +			  __PRETTY_FUNCTION__); +		return 0; +	} + +	igmp->igmp_group_list = list_new(); +	if (!igmp->igmp_group_list) { +		zlog_err("%s %s: failure: igmp_group_list = list_new()", +			 __FILE__, __PRETTY_FUNCTION__); +		return 0; +	} +	igmp->igmp_group_list->del = (void (*)(void *))igmp_group_free; + +	igmp->igmp_group_hash = +		hash_create(igmp_group_hash_key, igmp_group_hash_equal, NULL); + +	igmp->fd = fd; +	igmp->interface = ifp; +	igmp->ifaddr = ifaddr; +	igmp->t_igmp_read = NULL; +	igmp->t_igmp_query_timer = NULL; +	igmp->t_other_querier_timer = NULL; /* no other querier present */ +	igmp->querier_robustness_variable = +		pim_ifp->igmp_default_robustness_variable; +	igmp->sock_creation = pim_time_monotonic_sec(); + +	/* +	  igmp_startup_mode_on() will reset QQI: + +	  igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; +	*/ +	igmp_startup_mode_on(igmp); +	pim_igmp_general_query_on(igmp); + +	return igmp;  } -static void igmp_read_on (struct igmp_sock *igmp); +static void igmp_read_on(struct igmp_sock *igmp); -static int -pim_igmp_read (struct thread *t) +static int pim_igmp_read(struct thread *t)  { -  uint8_t buf[10000]; -  struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); -  struct sockaddr_in from; -  struct sockaddr_in to; -  socklen_t fromlen = sizeof(from); -  socklen_t tolen = sizeof(to); -  ifindex_t ifindex = -1; -  int cont = 1; -  int len; - -  while (cont) -    { -      len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), -				  &from, &fromlen, -				  &to, &tolen, -				  &ifindex); -      if (len < 0) -	{ -	  if (errno == EINTR) -	    continue; -	  if (errno == EWOULDBLOCK || errno == EAGAIN) -	    break; - -	  goto done; +	uint8_t buf[10000]; +	struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); +	struct sockaddr_in from; +	struct sockaddr_in to; +	socklen_t fromlen = sizeof(from); +	socklen_t tolen = sizeof(to); +	ifindex_t ifindex = -1; +	int cont = 1; +	int len; + +	while (cont) { +		len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), &from, +					    &fromlen, &to, &tolen, &ifindex); +		if (len < 0) { +			if (errno == EINTR) +				continue; +			if (errno == EWOULDBLOCK || errno == EAGAIN) +				break; + +			goto done; +		}  	} -    } - done: -  igmp_read_on(igmp); -  return 0; +done: +	igmp_read_on(igmp); +	return 0;  } -static void -igmp_read_on (struct igmp_sock *igmp) +static void igmp_read_on(struct igmp_sock *igmp)  { -  if (PIM_DEBUG_IGMP_TRACE_DETAIL) { -    zlog_debug("Scheduling READ event on IGMP socket fd=%d", -	       igmp->fd); -  } -  igmp->t_igmp_read = NULL; -  thread_add_read(master, pim_igmp_read, igmp, igmp->fd, &igmp->t_igmp_read); - +	if (PIM_DEBUG_IGMP_TRACE_DETAIL) { +		zlog_debug("Scheduling READ event on IGMP socket fd=%d", +			   igmp->fd); +	} +	igmp->t_igmp_read = NULL; +	thread_add_read(master, pim_igmp_read, igmp, igmp->fd, +			&igmp->t_igmp_read);  }  struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,  				    struct in_addr ifaddr,  				    struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct igmp_sock *igmp; -  int fd; +	struct pim_interface *pim_ifp; +	struct igmp_sock *igmp; +	int fd; -  pim_ifp = ifp->info; +	pim_ifp = ifp->info; -  fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options); -  if (fd < 0) { -    zlog_warn("Could not open IGMP socket for %s on %s", -	      inet_ntoa(ifaddr), ifp->name); -    return 0; -  } +	fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options); +	if (fd < 0) { +		zlog_warn("Could not open IGMP socket for %s on %s", +			  inet_ntoa(ifaddr), ifp->name); +		return 0; +	} -  igmp = igmp_sock_new(fd, ifaddr, ifp); -  if (!igmp) { -    zlog_err("%s %s: igmp_sock_new() failure", -	     __FILE__, __PRETTY_FUNCTION__); -    close(fd); -    return 0; -  } +	igmp = igmp_sock_new(fd, ifaddr, ifp); +	if (!igmp) { +		zlog_err("%s %s: igmp_sock_new() failure", __FILE__, +			 __PRETTY_FUNCTION__); +		close(fd); +		return 0; +	} -  igmp_read_on (igmp); +	igmp_read_on(igmp); -  listnode_add(igmp_sock_list, igmp); +	listnode_add(igmp_sock_list, igmp);  #ifdef IGMP_SOCK_DUMP -  igmp_sock_dump(igmp_sock_array); +	igmp_sock_dump(igmp_sock_array);  #endif -  return igmp; +	return igmp;  }  /* @@ -946,210 +956,203 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,   */  static int igmp_group_timer(struct thread *t)  { -  struct igmp_group *group; +	struct igmp_group *group; -  group = THREAD_ARG(t); +	group = THREAD_ARG(t); -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("%s: Timer for group %s on interface %s", -	       __PRETTY_FUNCTION__, -	       group_str, group->group_igmp_sock->interface->name); -  } +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("%s: Timer for group %s on interface %s", +			   __PRETTY_FUNCTION__, group_str, +			   group->group_igmp_sock->interface->name); +	} -  zassert(group->group_filtermode_isexcl); +	zassert(group->group_filtermode_isexcl); -  group->group_filtermode_isexcl = 0; +	group->group_filtermode_isexcl = 0; -  /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ -  igmp_anysource_forward_stop(group); +	/* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ +	igmp_anysource_forward_stop(group); -  igmp_source_delete_expired(group->group_source_list); +	igmp_source_delete_expired(group->group_source_list); -  zassert(!group->group_filtermode_isexcl); +	zassert(!group->group_filtermode_isexcl); -  /* -    RFC 3376: 6.2.2. Definition of Group Timers +	/* +	  RFC 3376: 6.2.2. Definition of Group Timers -    If there are no more source records for the group, delete group -    record. -  */ -  if (listcount(group->group_source_list) < 1) { -    igmp_group_delete_empty_include(group); -  } +	  If there are no more source records for the group, delete group +	  record. +	*/ +	if (listcount(group->group_source_list) < 1) { +		igmp_group_delete_empty_include(group); +	} -  return 0; +	return 0;  }  static void group_timer_off(struct igmp_group *group)  { -  if (!group->t_group_timer) -    return; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("Cancelling TIMER event for group %s on %s", -	       group_str, group->group_igmp_sock->interface->name); -  } -  THREAD_OFF(group->t_group_timer); +	if (!group->t_group_timer) +		return; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("Cancelling TIMER event for group %s on %s", +			   group_str, group->group_igmp_sock->interface->name); +	} +	THREAD_OFF(group->t_group_timer);  } -void igmp_group_timer_on(struct igmp_group *group, -			 long interval_msec, const char *ifname) +void igmp_group_timer_on(struct igmp_group *group, long interval_msec, +			 const char *ifname)  { -  group_timer_off(group); - -  if (PIM_DEBUG_IGMP_EVENTS) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s on %s", -	       interval_msec / 1000, -	       interval_msec % 1000, -	       group_str, ifname); -  } - -  /* -    RFC 3376: 6.2.2. Definition of Group Timers - -    The group timer is only used when a group is in EXCLUDE mode and -    it represents the time for the *filter-mode* of the group to -    expire and switch to INCLUDE mode. -  */ -  zassert(group->group_filtermode_isexcl); - -  thread_add_timer_msec(master, igmp_group_timer, group, interval_msec, -                        &group->t_group_timer); +	group_timer_off(group); + +	if (PIM_DEBUG_IGMP_EVENTS) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"Scheduling %ld.%03ld sec TIMER event for group %s on %s", +			interval_msec / 1000, interval_msec % 1000, group_str, +			ifname); +	} + +	/* +	  RFC 3376: 6.2.2. Definition of Group Timers + +	  The group timer is only used when a group is in EXCLUDE mode and +	  it represents the time for the *filter-mode* of the group to +	  expire and switch to INCLUDE mode. +	*/ +	zassert(group->group_filtermode_isexcl); + +	thread_add_timer_msec(master, igmp_group_timer, group, interval_msec, +			      &group->t_group_timer);  } -struct igmp_group * -find_group_by_addr (struct igmp_sock *igmp, -		   struct in_addr group_addr) +struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, +				      struct in_addr group_addr)  { -  struct igmp_group lookup; +	struct igmp_group lookup; -  lookup.group_addr.s_addr = group_addr.s_addr; +	lookup.group_addr.s_addr = group_addr.s_addr; -  return hash_lookup(igmp->igmp_group_hash, &lookup); +	return hash_lookup(igmp->igmp_group_hash, &lookup);  }  struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,  					  struct in_addr group_addr)  { -  struct igmp_group *group; - -  group = find_group_by_addr(igmp, group_addr); -  if (group) { -    return group; -  } - -  if (!pim_is_group_224_4 (group_addr)) -    { -      zlog_warn("%s: Group Specified is not part of 224.0.0.0/4", -		__PRETTY_FUNCTION__); -      return NULL; -    } - -  if (pim_is_group_224_0_0_0_24 (group_addr)) -    { -      zlog_warn("%s: Group specified is part of 224.0.0.0/24", -		__PRETTY_FUNCTION__); -      return NULL; -    } -  /* -    Non-existant group is created as INCLUDE {empty}: - -    RFC 3376 - 5.1. Action on Change of Interface State - -    If no interface state existed for that multicast address before -    the change (i.e., the change consisted of creating a new -    per-interface record), or if no state exists after the change -    (i.e., the change consisted of deleting a per-interface record), -    then the "non-existent" state is considered to have a filter mode -    of INCLUDE and an empty source list. -  */ - -  group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); -  if (!group) { -    zlog_warn("%s %s: XCALLOC() failure", -	      __FILE__, __PRETTY_FUNCTION__); -    return NULL; /* error, not found, could not create */ -  } - -  group->group_source_list = list_new(); -  if (!group->group_source_list) { -    zlog_warn("%s %s: list_new() failure", -	      __FILE__, __PRETTY_FUNCTION__); -    XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ -    return NULL; /* error, not found, could not initialize */ -  } -  group->group_source_list->del = (void (*)(void *)) igmp_source_free; - -  group->t_group_timer                         = NULL; -  group->t_group_query_retransmit_timer        = NULL; -  group->group_specific_query_retransmit_count = 0; -  group->group_addr                            = group_addr; -  group->group_igmp_sock                       = igmp; -  group->last_igmp_v1_report_dsec              = -1; -  group->last_igmp_v2_report_dsec              = -1; -  group->group_creation                        = pim_time_monotonic_sec(); -  group->igmp_version                          = IGMP_DEFAULT_VERSION; - -  /* initialize new group as INCLUDE {empty} */ -  group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */ - -  listnode_add(igmp->igmp_group_list, group); -  group = hash_get (igmp->igmp_group_hash, group, hash_alloc_intern); - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("Creating new IGMP group %s on socket %d interface %s", -	       group_str, igmp->fd, igmp->interface->name); -  } - -  /* -    RFC 3376: 6.2.2. Definition of Group Timers - -    The group timer is only used when a group is in EXCLUDE mode and -    it represents the time for the *filter-mode* of the group to -    expire and switch to INCLUDE mode. -  */ -  zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */ -  zassert(!group->t_group_timer); /* group timer == 0 */ - -  /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ -  igmp_anysource_forward_stop(group); - -  return group; +	struct igmp_group *group; + +	group = find_group_by_addr(igmp, group_addr); +	if (group) { +		return group; +	} + +	if (!pim_is_group_224_4(group_addr)) { +		zlog_warn("%s: Group Specified is not part of 224.0.0.0/4", +			  __PRETTY_FUNCTION__); +		return NULL; +	} + +	if (pim_is_group_224_0_0_0_24(group_addr)) { +		zlog_warn("%s: Group specified is part of 224.0.0.0/24", +			  __PRETTY_FUNCTION__); +		return NULL; +	} +	/* +	  Non-existant group is created as INCLUDE {empty}: + +	  RFC 3376 - 5.1. Action on Change of Interface State + +	  If no interface state existed for that multicast address before +	  the change (i.e., the change consisted of creating a new +	  per-interface record), or if no state exists after the change +	  (i.e., the change consisted of deleting a per-interface record), +	  then the "non-existent" state is considered to have a filter mode +	  of INCLUDE and an empty source list. +	*/ + +	group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); +	if (!group) { +		zlog_warn("%s %s: XCALLOC() failure", __FILE__, +			  __PRETTY_FUNCTION__); +		return NULL; /* error, not found, could not create */ +	} + +	group->group_source_list = list_new(); +	if (!group->group_source_list) { +		zlog_warn("%s %s: list_new() failure", __FILE__, +			  __PRETTY_FUNCTION__); +		XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ +		return NULL; /* error, not found, could not initialize */ +	} +	group->group_source_list->del = (void (*)(void *))igmp_source_free; + +	group->t_group_timer = NULL; +	group->t_group_query_retransmit_timer = NULL; +	group->group_specific_query_retransmit_count = 0; +	group->group_addr = group_addr; +	group->group_igmp_sock = igmp; +	group->last_igmp_v1_report_dsec = -1; +	group->last_igmp_v2_report_dsec = -1; +	group->group_creation = pim_time_monotonic_sec(); +	group->igmp_version = IGMP_DEFAULT_VERSION; + +	/* initialize new group as INCLUDE {empty} */ +	group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */ + +	listnode_add(igmp->igmp_group_list, group); +	group = hash_get(igmp->igmp_group_hash, group, hash_alloc_intern); + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"Creating new IGMP group %s on socket %d interface %s", +			group_str, igmp->fd, igmp->interface->name); +	} + +	/* +	  RFC 3376: 6.2.2. Definition of Group Timers + +	  The group timer is only used when a group is in EXCLUDE mode and +	  it represents the time for the *filter-mode* of the group to +	  expire and switch to INCLUDE mode. +	*/ +	zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */ +	zassert(!group->t_group_timer);		  /* group timer == 0 */ + +	/* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ +	igmp_anysource_forward_stop(group); + +	return group;  } -void -igmp_send_query (int igmp_version, -                 struct igmp_group *group, -                 int fd, -                 const char *ifname, -                 char *query_buf, -                 int query_buf_size, -                 int num_sources, -                 struct in_addr dst_addr, -                 struct in_addr group_addr, -                 int query_max_response_time_dsec, -                 uint8_t s_flag, -                 uint8_t querier_robustness_variable, -                 uint16_t querier_query_interval) +void igmp_send_query(int igmp_version, struct igmp_group *group, int fd, +		     const char *ifname, char *query_buf, int query_buf_size, +		     int num_sources, struct in_addr dst_addr, +		     struct in_addr group_addr, +		     int query_max_response_time_dsec, uint8_t s_flag, +		     uint8_t querier_robustness_variable, +		     uint16_t querier_query_interval)  { -  if (igmp_version == 3) { -    igmp_v3_send_query (group, fd, ifname, query_buf, -                        query_buf_size, num_sources, -                        dst_addr, group_addr, -                        query_max_response_time_dsec, s_flag, -                        querier_robustness_variable, -                        querier_query_interval); -  } else if (igmp_version == 2) { -    igmp_v2_send_query (group, fd, ifname, query_buf, -                        dst_addr, group_addr, -                        query_max_response_time_dsec); -  } +	if (igmp_version == 3) { +		igmp_v3_send_query(group, fd, ifname, query_buf, query_buf_size, +				   num_sources, dst_addr, group_addr, +				   query_max_response_time_dsec, s_flag, +				   querier_robustness_variable, +				   querier_query_interval); +	} else if (igmp_version == 2) { +		igmp_v2_send_query(group, fd, ifname, query_buf, dst_addr, +				   group_addr, query_max_response_time_dsec); +	}  } diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 2f36094bd3..275f25f63f 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -41,8 +41,8 @@  #define IGMP_V3_REPORT_HEADER_SIZE    (8)  #define IGMP_V3_GROUP_RECORD_MIN_SIZE (8) -#define IGMP_V3_MSG_MIN_SIZE          (IGMP_V3_REPORT_HEADER_SIZE + \ -				       IGMP_V3_GROUP_RECORD_MIN_SIZE) +#define IGMP_V3_MSG_MIN_SIZE                                                   \ +	(IGMP_V3_REPORT_HEADER_SIZE + IGMP_V3_GROUP_RECORD_MIN_SIZE)  #define IGMP_V12_MSG_SIZE             (8)  #define IGMP_V3_GROUP_RECORD_TYPE_OFFSET       (0) @@ -67,40 +67,40 @@  #define IGMP_DEFAULT_VERSION (3)  struct igmp_join { -  struct in_addr group_addr; -  struct in_addr source_addr; -  int            sock_fd; -  time_t         sock_creation; +	struct in_addr group_addr; +	struct in_addr source_addr; +	int sock_fd; +	time_t sock_creation;  };  struct igmp_sock { -  int               fd; -  struct interface *interface; -  struct in_addr    ifaddr; -  time_t            sock_creation; - -  struct thread    *t_igmp_read;                 /* read: IGMP sockets */ -  struct thread    *t_igmp_query_timer; /* timer: issue IGMP general queries */ -  struct thread    *t_other_querier_timer;   /* timer: other querier present */ - -  int               querier_query_interval;      /* QQI */ -  int               querier_robustness_variable; /* QRV */ -  int               startup_query_count; - -  struct list      *igmp_group_list; /* list of struct igmp_group */ -  struct hash      *igmp_group_hash; +	int fd; +	struct interface *interface; +	struct in_addr ifaddr; +	time_t sock_creation; + +	struct thread *t_igmp_read; /* read: IGMP sockets */ +	struct thread +		*t_igmp_query_timer; /* timer: issue IGMP general queries */ +	struct thread *t_other_querier_timer; /* timer: other querier present */ + +	int querier_query_interval;      /* QQI */ +	int querier_robustness_variable; /* QRV */ +	int startup_query_count; + +	struct list *igmp_group_list; /* list of struct igmp_group */ +	struct hash *igmp_group_hash;  };  struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,  					      struct in_addr ifaddr); -struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, -					 int fd); +struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd);  struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,  				    struct in_addr ifaddr,  				    struct interface *ifp);  void igmp_sock_delete(struct igmp_sock *igmp);  void igmp_sock_free(struct igmp_sock *igmp); -void igmp_sock_delete_all (struct interface *ifp); +void igmp_sock_delete_all(struct interface *ifp);  int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len);  void pim_igmp_general_query_on(struct igmp_sock *igmp); @@ -122,52 +122,53 @@ void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp);  #define IGMP_SOURCE_DONT_SEND(flags)       ((flags) &= ~IGMP_SOURCE_MASK_SEND)  struct igmp_source { -  struct in_addr      source_addr; -  struct thread      *t_source_timer; -  struct igmp_group  *source_group;    /* back pointer */ -  time_t              source_creation; -  uint32_t            source_flags; -  struct channel_oil *source_channel_oil; - -  /* -    RFC 3376: 6.6.3.2. Building and Sending Group and Source Specific Queries -  */ -  int                source_query_retransmit_count; +	struct in_addr source_addr; +	struct thread *t_source_timer; +	struct igmp_group *source_group; /* back pointer */ +	time_t source_creation; +	uint32_t source_flags; +	struct channel_oil *source_channel_oil; + +	/* +	  RFC 3376: 6.6.3.2. Building and Sending Group and Source Specific +	  Queries +	*/ +	int source_query_retransmit_count;  };  struct igmp_group { -  /* -    RFC 3376: 6.2.2. Definition of Group Timers - -    The group timer is only used when a group is in EXCLUDE mode and it -    represents the time for the *filter-mode* of the group to expire and -    switch to INCLUDE mode. -  */ -  struct thread    *t_group_timer; - -  /* Shared between group-specific and -     group-and-source-specific retransmissions */ -  struct thread    *t_group_query_retransmit_timer; - -  /* Counter exclusive for group-specific retransmissions -     (not used by group-and-source-specific retransmissions, -     since sources have their counters) */ -  int               group_specific_query_retransmit_count; - -  /* compatibility mode - igmp v1, v2 or v3 */ -  int               igmp_version; - -  struct in_addr    group_addr; -  int               group_filtermode_isexcl;  /* 0=INCLUDE, 1=EXCLUDE */ -  struct list      *group_source_list;        /* list of struct igmp_source */ -  time_t            group_creation; -  struct igmp_sock *group_igmp_sock;          /* back pointer */ -  int64_t           last_igmp_v1_report_dsec; -  int64_t           last_igmp_v2_report_dsec; +	/* +	  RFC 3376: 6.2.2. Definition of Group Timers + +	  The group timer is only used when a group is in EXCLUDE mode and it +	  represents the time for the *filter-mode* of the group to expire and +	  switch to INCLUDE mode. +	*/ +	struct thread *t_group_timer; + +	/* Shared between group-specific and +	   group-and-source-specific retransmissions */ +	struct thread *t_group_query_retransmit_timer; + +	/* Counter exclusive for group-specific retransmissions +	   (not used by group-and-source-specific retransmissions, +	   since sources have their counters) */ +	int group_specific_query_retransmit_count; + +	/* compatibility mode - igmp v1, v2 or v3 */ +	int igmp_version; + +	struct in_addr group_addr; +	int group_filtermode_isexcl;    /* 0=INCLUDE, 1=EXCLUDE */ +	struct list *group_source_list; /* list of struct igmp_source */ +	time_t group_creation; +	struct igmp_sock *group_igmp_sock; /* back pointer */ +	int64_t last_igmp_v1_report_dsec; +	int64_t last_igmp_v2_report_dsec;  }; -struct igmp_group *find_group_by_addr (struct igmp_sock *igmp, -				       struct in_addr group_addr); +struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, +				      struct in_addr group_addr);  struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,  					  struct in_addr group_addr); @@ -175,24 +176,17 @@ void igmp_group_delete_empty_include(struct igmp_group *group);  void igmp_startup_mode_on(struct igmp_sock *igmp); -void igmp_group_timer_on(struct igmp_group *group, -			 long interval_msec, const char *ifname); - -struct igmp_source * -source_new (struct igmp_group *group, -	    struct in_addr src_addr); - -void igmp_send_query(int igmp_version, -                     struct igmp_group *group, -                     int fd, -                     const char *ifname, -                     char *query_buf, -                     int query_buf_size, -                     int num_sources, -                     struct in_addr dst_addr, -                     struct in_addr group_addr, -                     int query_max_response_time_dsec, -                     uint8_t s_flag, -                     uint8_t querier_robustness_variable, -                     uint16_t querier_query_interval); +void igmp_group_timer_on(struct igmp_group *group, long interval_msec, +			 const char *ifname); + +struct igmp_source *source_new(struct igmp_group *group, +			       struct in_addr src_addr); + +void igmp_send_query(int igmp_version, struct igmp_group *group, int fd, +		     const char *ifname, char *query_buf, int query_buf_size, +		     int num_sources, struct in_addr dst_addr, +		     struct in_addr group_addr, +		     int query_max_response_time_dsec, uint8_t s_flag, +		     uint8_t querier_robustness_variable, +		     uint16_t querier_query_interval);  #endif /* PIM_IGMP_H */ diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 31fc1b0471..abee080064 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -28,11 +28,10 @@  #ifndef MCAST_JOIN_SOURCE_GROUP  #define MCAST_JOIN_SOURCE_GROUP 46 -struct group_source_req -{ -  uint32_t gsr_interface; -  struct sockaddr_storage gsr_group; -  struct sockaddr_storage gsr_source; +struct group_source_req { +	uint32_t gsr_interface; +	struct sockaddr_storage gsr_group; +	struct sockaddr_storage gsr_source;  };  #endif @@ -40,29 +39,29 @@ static int pim_igmp_join_source(int fd, ifindex_t ifindex,  				struct in_addr group_addr,  				struct in_addr source_addr)  { -  struct group_source_req req; -  struct sockaddr_in group; -  struct sockaddr_in source; +	struct group_source_req req; +	struct sockaddr_in group; +	struct sockaddr_in source; -  memset(&req, 0, sizeof(req)); -  memset(&group, 0, sizeof(group)); -  group.sin_family = AF_INET; -  group.sin_addr = group_addr; -  group.sin_port = htons(0); -  memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); +	memset(&req, 0, sizeof(req)); +	memset(&group, 0, sizeof(group)); +	group.sin_family = AF_INET; +	group.sin_addr = group_addr; +	group.sin_port = htons(0); +	memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); -  memset(&source, 0, sizeof(source)); -  source.sin_family = AF_INET; -  source.sin_addr = source_addr; -  source.sin_port = htons(0); -  memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); +	memset(&source, 0, sizeof(source)); +	source.sin_family = AF_INET; +	source.sin_addr = source_addr; +	source.sin_port = htons(0); +	memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); -  req.gsr_interface = ifindex; +	req.gsr_interface = ifindex; -  return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, -		    &req, sizeof(req)); +	return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, +			  sizeof(req)); -  return 0; +	return 0;  }  #endif /* PIM_IGMP_JOIN_H */ diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index d4b3010d3c..efa36e618f 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -29,161 +29,161 @@  #include "pim_util.h" -static void -on_trace (const char *label, -          struct interface *ifp, struct in_addr from) +static void on_trace(const char *label, struct interface *ifp, +		     struct in_addr from)  { -  if (PIM_DEBUG_IGMP_TRACE) { -    char from_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); -    zlog_debug("%s: from %s on %s", -               label, from_str, ifp->name); -  } +	if (PIM_DEBUG_IGMP_TRACE) { +		char from_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); +		zlog_debug("%s: from %s on %s", label, from_str, ifp->name); +	}  } -void -igmp_v2_send_query (struct igmp_group *group, -                    int fd, -                    const char *ifname, -                    char *query_buf, -                    struct in_addr dst_addr, -                    struct in_addr group_addr, -                    int query_max_response_time_dsec) +void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, +			char *query_buf, struct in_addr dst_addr, +			struct in_addr group_addr, +			int query_max_response_time_dsec)  { -  ssize_t             msg_size = 8; -  uint8_t             max_resp_code; -  ssize_t             sent; -  struct sockaddr_in  to; -  socklen_t           tolen; -  uint16_t            checksum; - -  /* max_resp_code must be non-zero else this will look like an IGMP v1 query */ -  max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); -  zassert(max_resp_code > 0); - -  query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; -  query_buf[1] = max_resp_code; -  *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET)   = 0; /* for computing checksum */ -  memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); - -  checksum = in_cksum(query_buf, msg_size); -  *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; - -  if (PIM_DEBUG_IGMP_PACKETS) { -    char dst_str[INET_ADDRSTRLEN]; -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); -    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); -    zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", -	       dst_str, ifname, group_str); -  } - -  memset(&to, 0, sizeof(to)); -  to.sin_family = AF_INET; -  to.sin_addr = dst_addr; -  tolen = sizeof(to); - -  sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, -                (struct sockaddr *)&to, tolen); -  if (sent != (ssize_t) msg_size) { -    char dst_str[INET_ADDRSTRLEN]; -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); -    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); -    if (sent < 0) { -      zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", -		dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); -    } -    else { -      zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", -		dst_str, ifname, group_str, msg_size, sent); -    } -    return; -  } +	ssize_t msg_size = 8; +	uint8_t max_resp_code; +	ssize_t sent; +	struct sockaddr_in to; +	socklen_t tolen; +	uint16_t checksum; + +	/* max_resp_code must be non-zero else this will look like an IGMP v1 +	 * query */ +	max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); +	zassert(max_resp_code > 0); + +	query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; +	query_buf[1] = max_resp_code; +	*(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = +		0; /* for computing checksum */ +	memcpy(query_buf + 4, &group_addr, sizeof(struct in_addr)); + +	checksum = in_cksum(query_buf, msg_size); +	*(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; + +	if (PIM_DEBUG_IGMP_PACKETS) { +		char dst_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); +		pim_inet4_dump("<group?>", group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", +			   dst_str, ifname, group_str); +	} + +	memset(&to, 0, sizeof(to)); +	to.sin_family = AF_INET; +	to.sin_addr = dst_addr; +	tolen = sizeof(to); + +	sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, +		      (struct sockaddr *)&to, tolen); +	if (sent != (ssize_t)msg_size) { +		char dst_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); +		pim_inet4_dump("<group?>", group_addr, group_str, +			       sizeof(group_str)); +		if (sent < 0) { +			zlog_warn( +				"Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", +				dst_str, ifname, group_str, msg_size, errno, +				safe_strerror(errno)); +		} else { +			zlog_warn( +				"Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", +				dst_str, ifname, group_str, msg_size, sent); +		} +		return; +	}  } -int -igmp_v2_recv_report (struct igmp_sock *igmp, -                     struct in_addr from, const char *from_str, -                     char *igmp_msg, int igmp_msg_len) +int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, +			const char *from_str, char *igmp_msg, int igmp_msg_len)  { -  struct interface *ifp = igmp->interface; -  struct in_addr group_addr; -  char group_str[INET_ADDRSTRLEN]; - -  on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - -  if (igmp_msg_len != IGMP_V12_MSG_SIZE) { -    zlog_warn("Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", -              from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); -    return -1; -  } - -  memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - -  if (PIM_DEBUG_IGMP_PACKETS) { -    pim_inet4_dump("<dst?>", group_addr, group_str, sizeof(group_str)); -    zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", -               from_str, ifp->name, group_str); -  } - -  /* -   * RFC 3376 -   * 7.3.2. In the Presence of Older Version Group Members -   * -   * When Group Compatibility Mode is IGMPv2, a router internally -   * translates the following IGMPv2 messages for that group to their -   * IGMPv3 equivalents: -   * -   * IGMPv2 Message                IGMPv3 Equivalent -   * --------------                ----------------- -   * Report                        IS_EX( {} ) -   * Leave                         TO_IN( {} ) -   */ -  igmpv3_report_isex (igmp, from, group_addr, 0, NULL, 1); - -  return 0; +	struct interface *ifp = igmp->interface; +	struct in_addr group_addr; +	char group_str[INET_ADDRSTRLEN]; + +	on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + +	if (igmp_msg_len != IGMP_V12_MSG_SIZE) { +		zlog_warn( +			"Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", +			from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); +		return -1; +	} + +	memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + +	if (PIM_DEBUG_IGMP_PACKETS) { +		pim_inet4_dump("<dst?>", group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", from_str, +			   ifp->name, group_str); +	} + +	/* +	 * RFC 3376 +	 * 7.3.2. In the Presence of Older Version Group Members +	 * +	 * When Group Compatibility Mode is IGMPv2, a router internally +	 * translates the following IGMPv2 messages for that group to their +	 * IGMPv3 equivalents: +	 * +	 * IGMPv2 Message                IGMPv3 Equivalent +	 * --------------                ----------------- +	 * Report                        IS_EX( {} ) +	 * Leave                         TO_IN( {} ) +	 */ +	igmpv3_report_isex(igmp, from, group_addr, 0, NULL, 1); + +	return 0;  } -int -igmp_v2_recv_leave (struct igmp_sock *igmp, -                    struct in_addr from, const char *from_str, -                    char *igmp_msg, int igmp_msg_len) +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, +		       const char *from_str, char *igmp_msg, int igmp_msg_len)  { -  struct interface *ifp = igmp->interface; -  struct in_addr group_addr; -  char group_str[INET_ADDRSTRLEN]; - -  on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - -  if (igmp_msg_len != IGMP_V12_MSG_SIZE) { -    zlog_warn("Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", -              from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); -    return -1; -  } - -  memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - -  if (PIM_DEBUG_IGMP_PACKETS) { -    pim_inet4_dump("<dst?>", group_addr, group_str, sizeof(group_str)); -    zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", -               from_str, ifp->name, group_str); -  } - -  /* -   * RFC 3376 -   * 7.3.2. In the Presence of Older Version Group Members -   * -   * When Group Compatibility Mode is IGMPv2, a router internally -   * translates the following IGMPv2 messages for that group to their -   * IGMPv3 equivalents: -   * -   * IGMPv2 Message                IGMPv3 Equivalent -   * --------------                ----------------- -   * Report                        IS_EX( {} ) -   * Leave                         TO_IN( {} ) -   */ -  igmpv3_report_toin (igmp, from, group_addr, 0, NULL); - -  return 0; +	struct interface *ifp = igmp->interface; +	struct in_addr group_addr; +	char group_str[INET_ADDRSTRLEN]; + +	on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + +	if (igmp_msg_len != IGMP_V12_MSG_SIZE) { +		zlog_warn( +			"Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", +			from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); +		return -1; +	} + +	memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + +	if (PIM_DEBUG_IGMP_PACKETS) { +		pim_inet4_dump("<dst?>", group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str, +			   ifp->name, group_str); +	} + +	/* +	 * RFC 3376 +	 * 7.3.2. In the Presence of Older Version Group Members +	 * +	 * When Group Compatibility Mode is IGMPv2, a router internally +	 * translates the following IGMPv2 messages for that group to their +	 * IGMPv3 equivalents: +	 * +	 * IGMPv2 Message                IGMPv3 Equivalent +	 * --------------                ----------------- +	 * Report                        IS_EX( {} ) +	 * Leave                         TO_IN( {} ) +	 */ +	igmpv3_report_toin(igmp, from, group_addr, 0, NULL); + +	return 0;  } diff --git a/pimd/pim_igmpv2.h b/pimd/pim_igmpv2.h index fa8d163944..f0a6fdc5fb 100644 --- a/pimd/pim_igmpv2.h +++ b/pimd/pim_igmpv2.h @@ -21,20 +21,15 @@  #ifndef PIM_IGMPV2_H  #define PIM_IGMPV2_H -void igmp_v2_send_query (struct igmp_group *group, -                         int fd, -                         const char *ifname, -                         char *query_buf, -                         struct in_addr dst_addr, -                         struct in_addr group_addr, -                         int query_max_response_time_dsec); +void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, +			char *query_buf, struct in_addr dst_addr, +			struct in_addr group_addr, +			int query_max_response_time_dsec); -int igmp_v2_recv_report (struct igmp_sock *igmp, -                         struct in_addr from, const char *from_str, -                         char *igmp_msg, int igmp_msg_len); +int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, +			const char *from_str, char *igmp_msg, int igmp_msg_len); -int igmp_v2_recv_leave (struct igmp_sock *igmp, -                        struct in_addr from, const char *from_str, -                        char *igmp_msg, int igmp_msg_len); +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, +		       const char *from_str, char *igmp_msg, int igmp_msg_len);  #endif /* PIM_IGMPV2_H */ diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index ad37ad8762..880d840eac 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -39,269 +39,270 @@ static void group_query_send(struct igmp_group *group);  static void source_query_send_by_flag(struct igmp_group *group,  				      int num_sources_tosend); -static void on_trace(const char *label, -		     struct interface *ifp, struct in_addr from, -		     struct in_addr group_addr, +static void on_trace(const char *label, struct interface *ifp, +		     struct in_addr from, struct in_addr group_addr,  		     int num_sources, struct in_addr *sources)  { -  if (PIM_DEBUG_IGMP_TRACE) { -    char from_str[INET_ADDRSTRLEN]; -    char group_str[INET_ADDRSTRLEN]; +	if (PIM_DEBUG_IGMP_TRACE) { +		char from_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); -    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); +		pim_inet4_dump("<from?>", from, from_str, sizeof(from_str)); +		pim_inet4_dump("<group?>", group_addr, group_str, +			       sizeof(group_str)); -    zlog_debug("%s: from %s on %s: group=%s sources=%d", -	       label, from_str, ifp->name, group_str, num_sources); -  } +		zlog_debug("%s: from %s on %s: group=%s sources=%d", label, +			   from_str, ifp->name, group_str, num_sources); +	}  }  void igmp_group_reset_gmi(struct igmp_group *group)  { -  long group_membership_interval_msec; -  struct pim_interface *pim_ifp; -  struct igmp_sock *igmp; -  struct interface *ifp; - -  igmp = group->group_igmp_sock; -  ifp = igmp->interface; -  pim_ifp = ifp->info; - -  /* -    RFC 3376: 8.4. Group Membership Interval - -    The Group Membership Interval is the amount of time that must pass -    before a multicast router decides there are no more members of a -    group or a particular source on a network. - -    This value MUST be ((the Robustness Variable) times (the Query -    Interval)) plus (one Query Response Interval). - -    group_membership_interval_msec = querier_robustness_variable * -                                     (1000 * querier_query_interval) + -                                     100 * query_response_interval_dsec; -  */ -  group_membership_interval_msec = -    PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, -		      igmp->querier_query_interval, -		      pim_ifp->igmp_query_max_response_time_dsec); - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("Resetting group %s timer to GMI=%ld.%03ld sec on %s", -	       group_str, -	       group_membership_interval_msec / 1000, -	       group_membership_interval_msec % 1000, -	       ifp->name); -  } - -  /* -    RFC 3376: 6.2.2. Definition of Group Timers - -    The group timer is only used when a group is in EXCLUDE mode and -    it represents the time for the *filter-mode* of the group to -    expire and switch to INCLUDE mode. -  */ -  zassert(group->group_filtermode_isexcl); - -  igmp_group_timer_on(group, group_membership_interval_msec, ifp->name); +	long group_membership_interval_msec; +	struct pim_interface *pim_ifp; +	struct igmp_sock *igmp; +	struct interface *ifp; + +	igmp = group->group_igmp_sock; +	ifp = igmp->interface; +	pim_ifp = ifp->info; + +	/* +	  RFC 3376: 8.4. Group Membership Interval + +	  The Group Membership Interval is the amount of time that must pass +	  before a multicast router decides there are no more members of a +	  group or a particular source on a network. + +	  This value MUST be ((the Robustness Variable) times (the Query +	  Interval)) plus (one Query Response Interval). + +	  group_membership_interval_msec = querier_robustness_variable * +					   (1000 * querier_query_interval) + +					   100 * query_response_interval_dsec; +	*/ +	group_membership_interval_msec = PIM_IGMP_GMI_MSEC( +		igmp->querier_robustness_variable, igmp->querier_query_interval, +		pim_ifp->igmp_query_max_response_time_dsec); + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"Resetting group %s timer to GMI=%ld.%03ld sec on %s", +			group_str, group_membership_interval_msec / 1000, +			group_membership_interval_msec % 1000, ifp->name); +	} + +	/* +	  RFC 3376: 6.2.2. Definition of Group Timers + +	  The group timer is only used when a group is in EXCLUDE mode and +	  it represents the time for the *filter-mode* of the group to +	  expire and switch to INCLUDE mode. +	*/ +	zassert(group->group_filtermode_isexcl); + +	igmp_group_timer_on(group, group_membership_interval_msec, ifp->name);  }  static int igmp_source_timer(struct thread *t)  { -  struct igmp_source *source; -  struct igmp_group *group; - -  source = THREAD_ARG(t); - -  group = source->source_group; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); -    zlog_debug("%s: Source timer expired for group %s source %s on %s", -	       __PRETTY_FUNCTION__, -	       group_str, source_str, -	       group->group_igmp_sock->interface->name); -  } - -  /* -    RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules - -    Group -    Filter-Mode    Source Timer Value    Action -    -----------    ------------------    ------ -    INCLUDE        TIMER == 0            Suggest to stop forwarding -                                         traffic from source and -                                         remove source record.  If -                                         there are no more source -                                         records for the group, delete -                                         group record. - -    EXCLUDE        TIMER == 0            Suggest to not forward -                                         traffic from source -                                         (DO NOT remove record) - -    Source timer switched from (T > 0) to (T == 0): disable forwarding. -   */ - -  if (group->group_filtermode_isexcl) { -    /* EXCLUDE mode */ - -    igmp_source_forward_stop(source); -  } -  else { -    /* INCLUDE mode */ - -    /* igmp_source_delete() will stop forwarding source */ -    igmp_source_delete(source); - -    /* -      If there are no more source records for the group, delete group -      record. -    */ -    if (!listcount(group->group_source_list)) { -      igmp_group_delete_empty_include(group); -    } -  } - -  return 0; +	struct igmp_source *source; +	struct igmp_group *group; + +	source = THREAD_ARG(t); + +	group = source->source_group; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", source->source_addr, source_str, +			       sizeof(source_str)); +		zlog_debug( +			"%s: Source timer expired for group %s source %s on %s", +			__PRETTY_FUNCTION__, group_str, source_str, +			group->group_igmp_sock->interface->name); +	} + +	/* +	  RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules + +	  Group +	  Filter-Mode    Source Timer Value    Action +	  -----------    ------------------    ------ +	  INCLUDE        TIMER == 0            Suggest to stop forwarding +					       traffic from source and +					       remove source record.  If +					       there are no more source +					       records for the group, delete +					       group record. + +	  EXCLUDE        TIMER == 0            Suggest to not forward +					       traffic from source +					       (DO NOT remove record) + +	  Source timer switched from (T > 0) to (T == 0): disable forwarding. +	 */ + +	if (group->group_filtermode_isexcl) { +		/* EXCLUDE mode */ + +		igmp_source_forward_stop(source); +	} else { +		/* INCLUDE mode */ + +		/* igmp_source_delete() will stop forwarding source */ +		igmp_source_delete(source); + +		/* +		  If there are no more source records for the group, delete +		  group +		  record. +		*/ +		if (!listcount(group->group_source_list)) { +			igmp_group_delete_empty_include(group); +		} +	} + +	return 0;  }  static void source_timer_off(struct igmp_group *group,  			     struct igmp_source *source)  { -  if (!source->t_source_timer) -    return; -   -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); -    zlog_debug("Cancelling TIMER event for group %s source %s on %s", -	       group_str, source_str, -	       group->group_igmp_sock->interface->name); -  } - -  THREAD_OFF(source->t_source_timer); +	if (!source->t_source_timer) +		return; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", source->source_addr, source_str, +			       sizeof(source_str)); +		zlog_debug( +			"Cancelling TIMER event for group %s source %s on %s", +			group_str, source_str, +			group->group_igmp_sock->interface->name); +	} + +	THREAD_OFF(source->t_source_timer);  }  static void igmp_source_timer_on(struct igmp_group *group, -				 struct igmp_source *source, -				 long interval_msec) +				 struct igmp_source *source, long interval_msec)  { -  source_timer_off(group, source); - -  if (PIM_DEBUG_IGMP_EVENTS) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); -    zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s", -	       interval_msec / 1000, -	       interval_msec % 1000, -	       group_str, source_str, -	       group->group_igmp_sock->interface->name); -  } - -  thread_add_timer_msec(master, igmp_source_timer, source, interval_msec, -                        &source->t_source_timer); - -  /* -    RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules -     -    Source timer switched from (T == 0) to (T > 0): enable forwarding. -  */ -  igmp_source_forward_start(source); +	source_timer_off(group, source); + +	if (PIM_DEBUG_IGMP_EVENTS) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", source->source_addr, source_str, +			       sizeof(source_str)); +		zlog_debug( +			"Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s", +			interval_msec / 1000, interval_msec % 1000, group_str, +			source_str, group->group_igmp_sock->interface->name); +	} + +	thread_add_timer_msec(master, igmp_source_timer, source, interval_msec, +			      &source->t_source_timer); + +	/* +	  RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules + +	  Source timer switched from (T == 0) to (T > 0): enable forwarding. +	*/ +	igmp_source_forward_start(source);  } -void igmp_source_reset_gmi(struct igmp_sock *igmp, -			   struct igmp_group *group, +void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group,  			   struct igmp_source *source)  { -  long group_membership_interval_msec; -  struct pim_interface *pim_ifp; -  struct interface *ifp; - -  ifp = igmp->interface; -  pim_ifp = ifp->info; - -  group_membership_interval_msec = -    PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, -		      igmp->querier_query_interval, -		      pim_ifp->igmp_query_max_response_time_dsec); - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; - -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); - -    zlog_debug("Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s", -	       source_str, -	       group_membership_interval_msec / 1000, -	       group_membership_interval_msec % 1000, -	       group_str, -	       ifp->name); -  } - -  igmp_source_timer_on(group, source, -		       group_membership_interval_msec); +	long group_membership_interval_msec; +	struct pim_interface *pim_ifp; +	struct interface *ifp; + +	ifp = igmp->interface; +	pim_ifp = ifp->info; + +	group_membership_interval_msec = PIM_IGMP_GMI_MSEC( +		igmp->querier_robustness_variable, igmp->querier_query_interval, +		pim_ifp->igmp_query_max_response_time_dsec); + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; + +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", source->source_addr, source_str, +			       sizeof(source_str)); + +		zlog_debug( +			"Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s", +			source_str, group_membership_interval_msec / 1000, +			group_membership_interval_msec % 1000, group_str, +			ifp->name); +	} + +	igmp_source_timer_on(group, source, group_membership_interval_msec);  }  static void source_mark_delete_flag(struct igmp_group *group)  { -  struct listnode    *src_node; -  struct igmp_source *src; +	struct listnode *src_node; +	struct igmp_source *src; -  for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) { -    IGMP_SOURCE_DO_DELETE(src->source_flags); -  } +	for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { +		IGMP_SOURCE_DO_DELETE(src->source_flags); +	}  } -static void source_mark_send_flag (struct igmp_group *group) +static void source_mark_send_flag(struct igmp_group *group)  { -  struct listnode    *src_node; -  struct igmp_source *src; +	struct listnode *src_node; +	struct igmp_source *src; -  for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) { -    IGMP_SOURCE_DO_SEND(src->source_flags); -  } +	for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { +		IGMP_SOURCE_DO_SEND(src->source_flags); +	}  } -static int source_mark_send_flag_by_timer (struct igmp_group *group) +static int source_mark_send_flag_by_timer(struct igmp_group *group)  { -  struct listnode    *src_node; -  struct igmp_source *src; -  int                 num_marked_sources = 0; - -  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { -    /* Is source timer running? */ -    if (src->t_source_timer) { -      IGMP_SOURCE_DO_SEND(src->source_flags); -      ++num_marked_sources; -    } -    else { -      IGMP_SOURCE_DONT_SEND(src->source_flags); -    } -  } - -  return num_marked_sources; +	struct listnode *src_node; +	struct igmp_source *src; +	int num_marked_sources = 0; + +	for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { +		/* Is source timer running? */ +		if (src->t_source_timer) { +			IGMP_SOURCE_DO_SEND(src->source_flags); +			++num_marked_sources; +		} else { +			IGMP_SOURCE_DONT_SEND(src->source_flags); +		} +	} + +	return num_marked_sources;  }  static void source_clear_send_flag(struct list *source_list)  { -  struct listnode    *src_node; -  struct igmp_source *src; +	struct listnode *src_node; +	struct igmp_source *src; -  for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) { -    IGMP_SOURCE_DONT_SEND(src->source_flags); -  } +	for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) { +		IGMP_SOURCE_DONT_SEND(src->source_flags); +	}  }  /* @@ -309,27 +310,27 @@ static void source_clear_send_flag(struct list *source_list)  */  static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group)  { -  zassert(group->group_filtermode_isexcl); +	zassert(group->group_filtermode_isexcl); -  if (listcount(group->group_source_list) < 1) { -    igmp_anysource_forward_start(group); -  } +	if (listcount(group->group_source_list) < 1) { +		igmp_anysource_forward_start(group); +	}  }  void igmp_source_free(struct igmp_source *source)  { -  /* make sure there is no source timer running */ -  zassert(!source->t_source_timer); +	/* make sure there is no source timer running */ +	zassert(!source->t_source_timer); -  XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source); +	XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source);  }  static void source_channel_oil_detach(struct igmp_source *source)  { -  if (source->source_channel_oil) { -    pim_channel_oil_del(source->source_channel_oil); -    source->source_channel_oil = NULL; -  } +	if (source->source_channel_oil) { +		pim_channel_oil_del(source->source_channel_oil); +		source->source_channel_oil = NULL; +	}  }  /* @@ -338,662 +339,659 @@ static void source_channel_oil_detach(struct igmp_source *source)  */  void igmp_source_delete(struct igmp_source *source)  { -  struct igmp_group *group; -  struct in_addr src; - -  group = source->source_group; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); -    zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d", -	       source_str, group_str, -	       group->group_igmp_sock->fd, -	       group->group_igmp_sock->interface->name, -               source->source_channel_oil ? source->source_channel_oil->oil_ref_count : 0); -  } - -  source_timer_off(group, source); -  igmp_source_forward_stop(source); - -  /* sanity check that forwarding has been disabled */ -  if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s", -	      __PRETTY_FUNCTION__, -	      source_str, group_str, -	      group->group_igmp_sock->fd, -	      group->group_igmp_sock->interface->name); -    /* warning only */ -  } - -  source_channel_oil_detach(source); - -  /* -    notice that listnode_delete() can't be moved -    into igmp_source_free() because the later is -    called by list_delete_all_node() -  */ -  listnode_delete(group->group_source_list, source); - -  src.s_addr = source->source_addr.s_addr; -  igmp_source_free(source); - -  /* Group source list is empty and current source is * then -   *,G group going away so do not trigger start */ -  if (group->group_filtermode_isexcl && -      (listcount (group->group_source_list) != 0) && -      src.s_addr != INADDR_ANY) -    { -      group_exclude_fwd_anysrc_ifempty (group); -    } +	struct igmp_group *group; +	struct in_addr src; + +	group = source->source_group; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", source->source_addr, source_str, +			       sizeof(source_str)); +		zlog_debug( +			"Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d", +			source_str, group_str, group->group_igmp_sock->fd, +			group->group_igmp_sock->interface->name, +			source->source_channel_oil +				? source->source_channel_oil->oil_ref_count +				: 0); +	} + +	source_timer_off(group, source); +	igmp_source_forward_stop(source); + +	/* sanity check that forwarding has been disabled */ +	if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", source->source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s", +			__PRETTY_FUNCTION__, source_str, group_str, +			group->group_igmp_sock->fd, +			group->group_igmp_sock->interface->name); +		/* warning only */ +	} + +	source_channel_oil_detach(source); + +	/* +	  notice that listnode_delete() can't be moved +	  into igmp_source_free() because the later is +	  called by list_delete_all_node() +	*/ +	listnode_delete(group->group_source_list, source); + +	src.s_addr = source->source_addr.s_addr; +	igmp_source_free(source); + +	/* Group source list is empty and current source is * then +	 *,G group going away so do not trigger start */ +	if (group->group_filtermode_isexcl +	    && (listcount(group->group_source_list) != 0) +	    && src.s_addr != INADDR_ANY) { +		group_exclude_fwd_anysrc_ifempty(group); +	}  }  static void source_delete_by_flag(struct list *source_list)  { -  struct listnode    *src_node; -  struct listnode    *src_nextnode; -  struct igmp_source *src; -   -  for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) -    if (IGMP_SOURCE_TEST_DELETE(src->source_flags)) -      igmp_source_delete(src); +	struct listnode *src_node; +	struct listnode *src_nextnode; +	struct igmp_source *src; + +	for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) +		if (IGMP_SOURCE_TEST_DELETE(src->source_flags)) +			igmp_source_delete(src);  }  void igmp_source_delete_expired(struct list *source_list)  { -  struct listnode    *src_node; -  struct listnode    *src_nextnode; -  struct igmp_source *src; -   -  for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) -    if (!src->t_source_timer) -      igmp_source_delete(src); +	struct listnode *src_node; +	struct listnode *src_nextnode; +	struct igmp_source *src; + +	for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) +		if (!src->t_source_timer) +			igmp_source_delete(src);  }  struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group,  					     struct in_addr src_addr)  { -  struct listnode    *src_node; -  struct igmp_source *src; +	struct listnode *src_node; +	struct igmp_source *src; -  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) -    if (src_addr.s_addr == src->source_addr.s_addr) -      return src; +	for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) +		if (src_addr.s_addr == src->source_addr.s_addr) +			return src; -  return 0; +	return 0;  } -struct igmp_source * -source_new (struct igmp_group *group, -	    struct in_addr src_addr) +struct igmp_source *source_new(struct igmp_group *group, +			       struct in_addr src_addr)  { -  struct igmp_source *src; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", src_addr, source_str, sizeof(source_str)); -    zlog_debug("Creating new IGMP source %s for group %s on socket %d interface %s", -	       source_str, group_str, -	       group->group_igmp_sock->fd, -	       group->group_igmp_sock->interface->name); -  } - -  src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); -  if (!src) { -    zlog_warn("%s %s: XCALLOC() failure", -	      __FILE__, __PRETTY_FUNCTION__); -    return 0; /* error, not found, could not create */ -  } -   -  src->t_source_timer                = NULL; -  src->source_group                  = group; /* back pointer */ -  src->source_addr                   = src_addr; -  src->source_creation               = pim_time_monotonic_sec(); -  src->source_flags                  = 0; -  src->source_query_retransmit_count = 0; -  src->source_channel_oil            = NULL; - -  listnode_add(group->group_source_list, src); - -  /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ -  igmp_anysource_forward_stop(group); - -  return src; +	struct igmp_source *src; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", src_addr, source_str, +			       sizeof(source_str)); +		zlog_debug( +			"Creating new IGMP source %s for group %s on socket %d interface %s", +			source_str, group_str, group->group_igmp_sock->fd, +			group->group_igmp_sock->interface->name); +	} + +	src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); +	if (!src) { +		zlog_warn("%s %s: XCALLOC() failure", __FILE__, +			  __PRETTY_FUNCTION__); +		return 0; /* error, not found, could not create */ +	} + +	src->t_source_timer = NULL; +	src->source_group = group; /* back pointer */ +	src->source_addr = src_addr; +	src->source_creation = pim_time_monotonic_sec(); +	src->source_flags = 0; +	src->source_query_retransmit_count = 0; +	src->source_channel_oil = NULL; + +	listnode_add(group->group_source_list, src); + +	/* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ +	igmp_anysource_forward_stop(group); + +	return src;  }  static struct igmp_source *add_source_by_addr(struct igmp_sock *igmp,  					      struct igmp_group *group,  					      struct in_addr src_addr)  { -  struct igmp_source *src; +	struct igmp_source *src; -  src = igmp_find_source_by_addr(group, src_addr); -  if (src) { -    return src; -  } +	src = igmp_find_source_by_addr(group, src_addr); +	if (src) { +		return src; +	} -  src = source_new(group, src_addr); -  if (!src) { -    return 0; -  } +	src = source_new(group, src_addr); +	if (!src) { +		return 0; +	} -  return src; +	return src;  }  static void allow(struct igmp_sock *igmp, struct in_addr from, -		  struct in_addr group_addr, -		  int num_sources, struct in_addr *sources) +		  struct in_addr group_addr, int num_sources, +		  struct in_addr *sources)  { -  struct igmp_source *source; -  struct igmp_group *group; -  int    i; - -  /* non-existant group is created as INCLUDE {empty} */ -  group = igmp_add_group_by_addr(igmp, group_addr); -  if (!group) { -    return; -  } - -  /* scan received sources */ -  for (i = 0; i < num_sources; ++i) { -    struct in_addr     *src_addr; - -    src_addr = sources + i; - -    source = add_source_by_addr(igmp, group, *src_addr); -    if (!source) { -      continue; -    } - -    /* -      RFC 3376: 6.4.1. Reception of Current-State Records - -      When receiving IS_IN reports for groups in EXCLUDE mode is -      sources should be moved from set with (timers = 0) to set with -      (timers > 0). - -      igmp_source_reset_gmi() below, resetting the source timers to -      GMI, accomplishes this. -    */ -    igmp_source_reset_gmi(igmp, group, source); - -  } /* scan received sources */ - -  if ((num_sources == 0) && -      (group->group_filtermode_isexcl) && -      (listcount (group->group_source_list) == 1)) -    { -      struct in_addr star = { .s_addr = INADDR_ANY }; - -      source = igmp_find_source_by_addr (group, star); -      if (source) -	igmp_source_reset_gmi (igmp, group, source); -    } +	struct igmp_source *source; +	struct igmp_group *group; +	int i; + +	/* non-existant group is created as INCLUDE {empty} */ +	group = igmp_add_group_by_addr(igmp, group_addr); +	if (!group) { +		return; +	} + +	/* scan received sources */ +	for (i = 0; i < num_sources; ++i) { +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		source = add_source_by_addr(igmp, group, *src_addr); +		if (!source) { +			continue; +		} + +		/* +		  RFC 3376: 6.4.1. Reception of Current-State Records + +		  When receiving IS_IN reports for groups in EXCLUDE mode is +		  sources should be moved from set with (timers = 0) to set with +		  (timers > 0). + +		  igmp_source_reset_gmi() below, resetting the source timers to +		  GMI, accomplishes this. +		*/ +		igmp_source_reset_gmi(igmp, group, source); + +	} /* scan received sources */ + +	if ((num_sources == 0) && (group->group_filtermode_isexcl) +	    && (listcount(group->group_source_list) == 1)) { +		struct in_addr star = {.s_addr = INADDR_ANY}; + +		source = igmp_find_source_by_addr(group, star); +		if (source) +			igmp_source_reset_gmi(igmp, group, source); +	}  }  void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -			int num_sources, struct in_addr *sources) +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources)  { -  on_trace(__PRETTY_FUNCTION__, -	   igmp->interface, from, group_addr, num_sources, sources); +	on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr, +		 num_sources, sources); -  allow(igmp, from, group_addr, num_sources, sources); +	allow(igmp, from, group_addr, num_sources, sources);  } -static void isex_excl(struct igmp_group *group, -		      int num_sources, struct in_addr *sources) +static void isex_excl(struct igmp_group *group, int num_sources, +		      struct in_addr *sources)  { -  struct igmp_source *source; -  int     i; - -  /* EXCLUDE mode */ -  zassert(group->group_filtermode_isexcl); -   -  /* E.1: set deletion flag for known sources (X,Y) */ -  source_mark_delete_flag (group); - -  /* scan received sources (A) */ -  for (i = 0; i < num_sources; ++i) { -    struct in_addr     *src_addr; - -    src_addr = sources + i; - -    /* E.2: lookup reported source from (A) in (X,Y) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (source) { -      /* E.3: if found, clear deletion flag: (X*A) or (Y*A) */ -      IGMP_SOURCE_DONT_DELETE(source->source_flags); -    } -    else { -      /* E.4: if not found, create source with timer=GMI: (A-X-Y) */ -      source = source_new(group, *src_addr); -      if (!source) { -	/* ugh, internal malloc failure, skip source */ -	continue; -      } -      zassert(!source->t_source_timer); /* timer == 0 */ -      igmp_source_reset_gmi(group->group_igmp_sock, group, source); -      zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ -    } - -  } /* scan received sources */ - -  /* -   * If we are in isexcl mode and num_sources == 0 -   * than that means we have a *,g entry that -   * needs to be handled -   */ -  if (group->group_filtermode_isexcl && num_sources == 0) -    { -       struct in_addr star = { .s_addr = INADDR_ANY }; -       source = igmp_find_source_by_addr (group, star); -       if (source) -         { -           IGMP_SOURCE_DONT_DELETE(source->source_flags); -           igmp_source_reset_gmi (group->group_igmp_sock, group, source); -         } -    } - -  /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */ -  source_delete_by_flag(group->group_source_list); +	struct igmp_source *source; +	int i; + +	/* EXCLUDE mode */ +	zassert(group->group_filtermode_isexcl); + +	/* E.1: set deletion flag for known sources (X,Y) */ +	source_mark_delete_flag(group); + +	/* scan received sources (A) */ +	for (i = 0; i < num_sources; ++i) { +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* E.2: lookup reported source from (A) in (X,Y) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (source) { +			/* E.3: if found, clear deletion flag: (X*A) or (Y*A) */ +			IGMP_SOURCE_DONT_DELETE(source->source_flags); +		} else { +			/* E.4: if not found, create source with timer=GMI: +			 * (A-X-Y) */ +			source = source_new(group, *src_addr); +			if (!source) { +				/* ugh, internal malloc failure, skip source */ +				continue; +			} +			zassert(!source->t_source_timer); /* timer == 0 */ +			igmp_source_reset_gmi(group->group_igmp_sock, group, +					      source); +			zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ +		} + +	} /* scan received sources */ + +	/* +	 * If we are in isexcl mode and num_sources == 0 +	 * than that means we have a *,g entry that +	 * needs to be handled +	 */ +	if (group->group_filtermode_isexcl && num_sources == 0) { +		struct in_addr star = {.s_addr = INADDR_ANY}; +		source = igmp_find_source_by_addr(group, star); +		if (source) { +			IGMP_SOURCE_DONT_DELETE(source->source_flags); +			igmp_source_reset_gmi(group->group_igmp_sock, group, +					      source); +		} +	} + +	/* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */ +	source_delete_by_flag(group->group_source_list);  } -static void isex_incl(struct igmp_group *group, -		      int num_sources, struct in_addr *sources) +static void isex_incl(struct igmp_group *group, int num_sources, +		      struct in_addr *sources)  { -  int i; - -  /* INCLUDE mode */ -  zassert(!group->group_filtermode_isexcl); -   -  /* I.1: set deletion flag for known sources (A) */ -  source_mark_delete_flag (group); - -  /* scan received sources (B) */ -  for (i = 0; i < num_sources; ++i) { -    struct igmp_source *source; -    struct in_addr     *src_addr; - -    src_addr = sources + i; - -    /* I.2: lookup reported source (B) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (source) { -      /* I.3: if found, clear deletion flag (A*B) */ -      IGMP_SOURCE_DONT_DELETE(source->source_flags); -    } -    else { -      /* I.4: if not found, create source with timer=0 (B-A) */ -      source = source_new(group, *src_addr); -      if (!source) { -	/* ugh, internal malloc failure, skip source */ -	continue; -      } -      zassert(!source->t_source_timer); /* (B-A) timer=0 */ -    } - -  } /* scan received sources */ - -  /* I.5: delete all sources marked with deletion flag (A-B) */ -  source_delete_by_flag(group->group_source_list); - -  group->group_filtermode_isexcl = 1; /* boolean=true */ - -  zassert(group->group_filtermode_isexcl); - -  group_exclude_fwd_anysrc_ifempty(group); +	int i; + +	/* INCLUDE mode */ +	zassert(!group->group_filtermode_isexcl); + +	/* I.1: set deletion flag for known sources (A) */ +	source_mark_delete_flag(group); + +	/* scan received sources (B) */ +	for (i = 0; i < num_sources; ++i) { +		struct igmp_source *source; +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* I.2: lookup reported source (B) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (source) { +			/* I.3: if found, clear deletion flag (A*B) */ +			IGMP_SOURCE_DONT_DELETE(source->source_flags); +		} else { +			/* I.4: if not found, create source with timer=0 (B-A) +			 */ +			source = source_new(group, *src_addr); +			if (!source) { +				/* ugh, internal malloc failure, skip source */ +				continue; +			} +			zassert(!source->t_source_timer); /* (B-A) timer=0 */ +		} + +	} /* scan received sources */ + +	/* I.5: delete all sources marked with deletion flag (A-B) */ +	source_delete_by_flag(group->group_source_list); + +	group->group_filtermode_isexcl = 1; /* boolean=true */ + +	zassert(group->group_filtermode_isexcl); + +	group_exclude_fwd_anysrc_ifempty(group);  }  void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -			int num_sources, struct in_addr *sources, -                        int from_igmp_v2_report) +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources, int from_igmp_v2_report)  { -  struct interface *ifp = igmp->interface; -  struct igmp_group *group; - -  on_trace(__PRETTY_FUNCTION__, -	   ifp, from, group_addr, num_sources, sources); - -  /* non-existant group is created as INCLUDE {empty} */ -  group = igmp_add_group_by_addr(igmp, group_addr); -  if (!group) { -    return; -  } - -  /* So we can display how we learned the group in our show command output */ -  if (from_igmp_v2_report) -    group->igmp_version = 2; - -  if (group->group_filtermode_isexcl) { -    /* EXCLUDE mode */ -    isex_excl(group, num_sources, sources); -  } -  else { -    /* INCLUDE mode */ -    isex_incl(group, num_sources, sources); -    zassert(group->group_filtermode_isexcl); -  } - -  zassert(group->group_filtermode_isexcl); - -  igmp_group_reset_gmi(group); +	struct interface *ifp = igmp->interface; +	struct igmp_group *group; + +	on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, +		 sources); + +	/* non-existant group is created as INCLUDE {empty} */ +	group = igmp_add_group_by_addr(igmp, group_addr); +	if (!group) { +		return; +	} + +	/* So we can display how we learned the group in our show command output +	 */ +	if (from_igmp_v2_report) +		group->igmp_version = 2; + +	if (group->group_filtermode_isexcl) { +		/* EXCLUDE mode */ +		isex_excl(group, num_sources, sources); +	} else { +		/* INCLUDE mode */ +		isex_incl(group, num_sources, sources); +		zassert(group->group_filtermode_isexcl); +	} + +	zassert(group->group_filtermode_isexcl); + +	igmp_group_reset_gmi(group);  } -static void toin_incl(struct igmp_group *group, -		      int num_sources, struct in_addr *sources) +static void toin_incl(struct igmp_group *group, int num_sources, +		      struct in_addr *sources)  { -  struct igmp_sock *igmp = group->group_igmp_sock; -  int num_sources_tosend = listcount(group->group_source_list); -  int i; - -  /* Set SEND flag for all known sources (A) */ -  source_mark_send_flag (group); - -  /* Scan received sources (B) */ -  for (i = 0; i < num_sources; ++i) { -    struct igmp_source *source; -    struct in_addr     *src_addr; - -    src_addr = sources + i; - -    /* Lookup reported source (B) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (source) { -      /* If found, clear SEND flag (A*B) */ -      IGMP_SOURCE_DONT_SEND(source->source_flags); -      --num_sources_tosend; -    } -    else { -      /* If not found, create new source */ -      source = source_new(group, *src_addr); -      if (!source) { -	/* ugh, internal malloc failure, skip source */ -	continue; -      } -    } - -    /* (B)=GMI */ -    igmp_source_reset_gmi(igmp, group, source); -  } - -  /* Send sources marked with SEND flag: Q(G,A-B) */ -  if (num_sources_tosend > 0) { -    source_query_send_by_flag(group, num_sources_tosend); -  } +	struct igmp_sock *igmp = group->group_igmp_sock; +	int num_sources_tosend = listcount(group->group_source_list); +	int i; + +	/* Set SEND flag for all known sources (A) */ +	source_mark_send_flag(group); + +	/* Scan received sources (B) */ +	for (i = 0; i < num_sources; ++i) { +		struct igmp_source *source; +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* Lookup reported source (B) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (source) { +			/* If found, clear SEND flag (A*B) */ +			IGMP_SOURCE_DONT_SEND(source->source_flags); +			--num_sources_tosend; +		} else { +			/* If not found, create new source */ +			source = source_new(group, *src_addr); +			if (!source) { +				/* ugh, internal malloc failure, skip source */ +				continue; +			} +		} + +		/* (B)=GMI */ +		igmp_source_reset_gmi(igmp, group, source); +	} + +	/* Send sources marked with SEND flag: Q(G,A-B) */ +	if (num_sources_tosend > 0) { +		source_query_send_by_flag(group, num_sources_tosend); +	}  } -static void toin_excl(struct igmp_group *group, -		      int num_sources, struct in_addr *sources) +static void toin_excl(struct igmp_group *group, int num_sources, +		      struct in_addr *sources)  { -  struct igmp_sock *igmp = group->group_igmp_sock; -  int num_sources_tosend; -  int i; - -  /* Set SEND flag for X (sources with timer > 0) */ -  num_sources_tosend = source_mark_send_flag_by_timer (group); - -  /* Scan received sources (A) */ -  for (i = 0; i < num_sources; ++i) { -    struct igmp_source *source; -    struct in_addr     *src_addr; - -    src_addr = sources + i; - -    /* Lookup reported source (A) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (source) { -      if (source->t_source_timer) { -	/* If found and timer running, clear SEND flag (X*A) */ -	IGMP_SOURCE_DONT_SEND(source->source_flags); -	--num_sources_tosend; -      } -    } -    else { -      /* If not found, create new source */ -      source = source_new(group, *src_addr); -      if (!source) { -	/* ugh, internal malloc failure, skip source */ -	continue; -      } -    } - -    /* (A)=GMI */ -    igmp_source_reset_gmi(igmp, group, source); -  } - -  /* Send sources marked with SEND flag: Q(G,X-A) */ -  if (num_sources_tosend > 0) { -    source_query_send_by_flag(group, num_sources_tosend); -  } - -  /* Send Q(G) */ -  group_query_send(group); +	struct igmp_sock *igmp = group->group_igmp_sock; +	int num_sources_tosend; +	int i; + +	/* Set SEND flag for X (sources with timer > 0) */ +	num_sources_tosend = source_mark_send_flag_by_timer(group); + +	/* Scan received sources (A) */ +	for (i = 0; i < num_sources; ++i) { +		struct igmp_source *source; +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* Lookup reported source (A) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (source) { +			if (source->t_source_timer) { +				/* If found and timer running, clear SEND flag +				 * (X*A) */ +				IGMP_SOURCE_DONT_SEND(source->source_flags); +				--num_sources_tosend; +			} +		} else { +			/* If not found, create new source */ +			source = source_new(group, *src_addr); +			if (!source) { +				/* ugh, internal malloc failure, skip source */ +				continue; +			} +		} + +		/* (A)=GMI */ +		igmp_source_reset_gmi(igmp, group, source); +	} + +	/* Send sources marked with SEND flag: Q(G,X-A) */ +	if (num_sources_tosend > 0) { +		source_query_send_by_flag(group, num_sources_tosend); +	} + +	/* Send Q(G) */ +	group_query_send(group);  }  void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -			int num_sources, struct in_addr *sources) +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources)  { -  struct interface *ifp = igmp->interface; -  struct igmp_group *group; - -  on_trace(__PRETTY_FUNCTION__, -	   ifp, from, group_addr, num_sources, sources); - -  /* -   * If the requested filter mode is INCLUDE *and* the requested source -   * list is empty, then the entry corresponding to the requested -   * interface and multicast address is deleted if present.  If no such -   * entry is present, the request is ignored. -   */ -  if (num_sources) -    { -      /* non-existant group is created as INCLUDE {empty} */ -      group = igmp_add_group_by_addr(igmp, group_addr); -      if (!group) { -	return; -      } -    } -  else -    { -      group = find_group_by_addr (igmp, group_addr); -      if (!group) -	return; -    } - -  if (group->group_filtermode_isexcl) { -    /* EXCLUDE mode */ -    toin_excl(group, num_sources, sources); -  } -  else { -    /* INCLUDE mode */ -    toin_incl(group, num_sources, sources); -  } +	struct interface *ifp = igmp->interface; +	struct igmp_group *group; + +	on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, +		 sources); + +	/* +	 * If the requested filter mode is INCLUDE *and* the requested source +	 * list is empty, then the entry corresponding to the requested +	 * interface and multicast address is deleted if present.  If no such +	 * entry is present, the request is ignored. +	 */ +	if (num_sources) { +		/* non-existant group is created as INCLUDE {empty} */ +		group = igmp_add_group_by_addr(igmp, group_addr); +		if (!group) { +			return; +		} +	} else { +		group = find_group_by_addr(igmp, group_addr); +		if (!group) +			return; +	} + +	if (group->group_filtermode_isexcl) { +		/* EXCLUDE mode */ +		toin_excl(group, num_sources, sources); +	} else { +		/* INCLUDE mode */ +		toin_incl(group, num_sources, sources); +	}  } -static void toex_incl(struct igmp_group *group, -		      int num_sources, struct in_addr *sources) +static void toex_incl(struct igmp_group *group, int num_sources, +		      struct in_addr *sources)  { -  int num_sources_tosend = 0; -  int i; - -  zassert(!group->group_filtermode_isexcl); - -  /* Set DELETE flag for all known sources (A) */ -  source_mark_delete_flag (group); - -  /* Clear off SEND flag from all known sources (A) */ -  source_clear_send_flag(group->group_source_list); - -  /* Scan received sources (B) */ -  for (i = 0; i < num_sources; ++i) { -    struct igmp_source *source; -    struct in_addr     *src_addr; - -    src_addr = sources + i; - -    /* Lookup reported source (B) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (source) { -      /* If found, clear deletion flag: (A*B) */ -      IGMP_SOURCE_DONT_DELETE(source->source_flags); -      /* and set SEND flag (A*B) */ -      IGMP_SOURCE_DO_SEND(source->source_flags); -      ++num_sources_tosend; -    } -    else { -      /* If source not found, create source with timer=0: (B-A)=0 */ -      source = source_new(group, *src_addr); -      if (!source) { -	/* ugh, internal malloc failure, skip source */ -	continue; -      } -      zassert(!source->t_source_timer); /* (B-A) timer=0 */ -    } - -  } /* Scan received sources (B) */ - -  group->group_filtermode_isexcl = 1; /* boolean=true */ - -  /* Delete all sources marked with DELETE flag (A-B) */ -  source_delete_by_flag(group->group_source_list); - -  /* Send sources marked with SEND flag: Q(G,A*B) */ -  if (num_sources_tosend > 0) { -    source_query_send_by_flag(group, num_sources_tosend); -  } - -  zassert(group->group_filtermode_isexcl); - -  group_exclude_fwd_anysrc_ifempty(group); +	int num_sources_tosend = 0; +	int i; + +	zassert(!group->group_filtermode_isexcl); + +	/* Set DELETE flag for all known sources (A) */ +	source_mark_delete_flag(group); + +	/* Clear off SEND flag from all known sources (A) */ +	source_clear_send_flag(group->group_source_list); + +	/* Scan received sources (B) */ +	for (i = 0; i < num_sources; ++i) { +		struct igmp_source *source; +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* Lookup reported source (B) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (source) { +			/* If found, clear deletion flag: (A*B) */ +			IGMP_SOURCE_DONT_DELETE(source->source_flags); +			/* and set SEND flag (A*B) */ +			IGMP_SOURCE_DO_SEND(source->source_flags); +			++num_sources_tosend; +		} else { +			/* If source not found, create source with timer=0: +			 * (B-A)=0 */ +			source = source_new(group, *src_addr); +			if (!source) { +				/* ugh, internal malloc failure, skip source */ +				continue; +			} +			zassert(!source->t_source_timer); /* (B-A) timer=0 */ +		} + +	} /* Scan received sources (B) */ + +	group->group_filtermode_isexcl = 1; /* boolean=true */ + +	/* Delete all sources marked with DELETE flag (A-B) */ +	source_delete_by_flag(group->group_source_list); + +	/* Send sources marked with SEND flag: Q(G,A*B) */ +	if (num_sources_tosend > 0) { +		source_query_send_by_flag(group, num_sources_tosend); +	} + +	zassert(group->group_filtermode_isexcl); + +	group_exclude_fwd_anysrc_ifempty(group);  } -static void toex_excl(struct igmp_group *group, -		      int num_sources, struct in_addr *sources) +static void toex_excl(struct igmp_group *group, int num_sources, +		      struct in_addr *sources)  { -  int num_sources_tosend = 0; -  int i; - -  /* set DELETE flag for all known sources (X,Y) */ -  source_mark_delete_flag (group); - -  /* clear off SEND flag from all known sources (X,Y) */ -  source_clear_send_flag(group->group_source_list); - -  if (num_sources == 0) -    { -      struct igmp_source *source; -      struct in_addr any = { .s_addr = INADDR_ANY }; - -      source = igmp_find_source_by_addr (group, any); -      if (source) -        IGMP_SOURCE_DONT_DELETE(source->source_flags); -    } - -  /* scan received sources (A) */ -  for (i = 0; i < num_sources; ++i) { -    struct igmp_source *source; -    struct in_addr     *src_addr; -     -    src_addr = sources + i; -     -    /* lookup reported source (A) in known sources (X,Y) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (source) { -      /* if found, clear off DELETE flag from reported source (A) */ -      IGMP_SOURCE_DONT_DELETE(source->source_flags); -    } -    else { -      /* if not found, create source with Group Timer: (A-X-Y)=Group Timer */ -      long group_timer_msec; -      source = source_new(group, *src_addr); -      if (!source) { -	/* ugh, internal malloc failure, skip source */ -	continue; -      } - -      zassert(!source->t_source_timer); /* timer == 0 */ -      group_timer_msec = igmp_group_timer_remain_msec(group); -      igmp_source_timer_on(group, source, group_timer_msec); -      zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ - -      /* make sure source is created with DELETE flag unset */ -      zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); -    } - -    /* make sure reported source has DELETE flag unset */ -    zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); - -    if (source->t_source_timer) { -      /* if source timer>0 mark SEND flag: Q(G,A-Y) */ -      IGMP_SOURCE_DO_SEND(source->source_flags); -      ++num_sources_tosend; -    } - -  } /* scan received sources (A) */ - -  /* -    delete all sources marked with DELETE flag: -    Delete (X-A) -    Delete (Y-A) -  */ -  source_delete_by_flag(group->group_source_list); -  -  /* send sources marked with SEND flag: Q(G,A-Y) */ -  if (num_sources_tosend > 0) { -    source_query_send_by_flag(group, num_sources_tosend); -  } +	int num_sources_tosend = 0; +	int i; + +	/* set DELETE flag for all known sources (X,Y) */ +	source_mark_delete_flag(group); + +	/* clear off SEND flag from all known sources (X,Y) */ +	source_clear_send_flag(group->group_source_list); + +	if (num_sources == 0) { +		struct igmp_source *source; +		struct in_addr any = {.s_addr = INADDR_ANY}; + +		source = igmp_find_source_by_addr(group, any); +		if (source) +			IGMP_SOURCE_DONT_DELETE(source->source_flags); +	} + +	/* scan received sources (A) */ +	for (i = 0; i < num_sources; ++i) { +		struct igmp_source *source; +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* lookup reported source (A) in known sources (X,Y) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (source) { +			/* if found, clear off DELETE flag from reported source +			 * (A) */ +			IGMP_SOURCE_DONT_DELETE(source->source_flags); +		} else { +			/* if not found, create source with Group Timer: +			 * (A-X-Y)=Group Timer */ +			long group_timer_msec; +			source = source_new(group, *src_addr); +			if (!source) { +				/* ugh, internal malloc failure, skip source */ +				continue; +			} + +			zassert(!source->t_source_timer); /* timer == 0 */ +			group_timer_msec = igmp_group_timer_remain_msec(group); +			igmp_source_timer_on(group, source, group_timer_msec); +			zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + +			/* make sure source is created with DELETE flag unset */ +			zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); +		} + +		/* make sure reported source has DELETE flag unset */ +		zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); + +		if (source->t_source_timer) { +			/* if source timer>0 mark SEND flag: Q(G,A-Y) */ +			IGMP_SOURCE_DO_SEND(source->source_flags); +			++num_sources_tosend; +		} + +	} /* scan received sources (A) */ + +	/* +	  delete all sources marked with DELETE flag: +	  Delete (X-A) +	  Delete (Y-A) +	*/ +	source_delete_by_flag(group->group_source_list); + +	/* send sources marked with SEND flag: Q(G,A-Y) */ +	if (num_sources_tosend > 0) { +		source_query_send_by_flag(group, num_sources_tosend); +	}  }  void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -			int num_sources, struct in_addr *sources) +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources)  { -  struct interface *ifp = igmp->interface; -  struct igmp_group *group; - -  on_trace(__PRETTY_FUNCTION__, -	   ifp, from, group_addr, num_sources, sources); - -  /* non-existant group is created as INCLUDE {empty} */ -  group = igmp_add_group_by_addr(igmp, group_addr); -  if (!group) { -    return; -  } - -  if (group->group_filtermode_isexcl) { -    /* EXCLUDE mode */ -    toex_excl(group, num_sources, sources); -  } -  else { -    /* INCLUDE mode */ -    toex_incl(group, num_sources, sources); -    zassert(group->group_filtermode_isexcl); -  } -  zassert(group->group_filtermode_isexcl); - -  /* Group Timer=GMI */ -  igmp_group_reset_gmi(group); +	struct interface *ifp = igmp->interface; +	struct igmp_group *group; + +	on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, +		 sources); + +	/* non-existant group is created as INCLUDE {empty} */ +	group = igmp_add_group_by_addr(igmp, group_addr); +	if (!group) { +		return; +	} + +	if (group->group_filtermode_isexcl) { +		/* EXCLUDE mode */ +		toex_excl(group, num_sources, sources); +	} else { +		/* INCLUDE mode */ +		toex_incl(group, num_sources, sources); +		zassert(group->group_filtermode_isexcl); +	} +	zassert(group->group_filtermode_isexcl); + +	/* Group Timer=GMI */ +	igmp_group_reset_gmi(group);  }  void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, -			 struct in_addr group_addr, -			 int num_sources, struct in_addr *sources) +			 struct in_addr group_addr, int num_sources, +			 struct in_addr *sources)  { -  on_trace(__PRETTY_FUNCTION__, -	   igmp->interface, from, group_addr, num_sources, sources); +	on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr, +		 num_sources, sources); -  allow(igmp, from, group_addr, num_sources, sources); +	allow(igmp, from, group_addr, num_sources, sources);  }  /* @@ -1005,67 +1003,64 @@ void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from,  */  static void group_retransmit_group(struct igmp_group *group)  { -  struct igmp_sock     *igmp; -  struct pim_interface *pim_ifp; -  long                  lmqc;      /* Last Member Query Count */ -  long                  lmqi_msec; /* Last Member Query Interval */ -  long                  lmqt_msec; /* Last Member Query Time */ -  int                   s_flag; -  int                   query_buf_size; - -  igmp = group->group_igmp_sock; -  pim_ifp = igmp->interface->info; - -  if (pim_ifp->igmp_version == 3) { -    query_buf_size = PIM_IGMP_BUFSIZE_WRITE; -  } else { -    query_buf_size = IGMP_V12_MSG_SIZE; -  } - -  char query_buf[query_buf_size]; - -  lmqc      = igmp->querier_robustness_variable; -  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; -  lmqt_msec = lmqc * lmqi_msec; - -  /* -    RFC3376: 6.6.3.1. Building and Sending Group Specific Queries -     -    When transmitting a group specific query, if the group timer is -    larger than LMQT, the "Suppress Router-Side Processing" bit is set -    in the query message. -  */ -  s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d", -	       group_str, igmp->interface->name, s_flag, -	       group->group_specific_query_retransmit_count); -  } - -  /* -    RFC3376: 4.1.12. IP Destination Addresses for Queries - -    Group-Specific and Group-and-Source-Specific Queries are sent with -    an IP destination address equal to the multicast address of -    interest. -  */ - -  igmp_send_query(pim_ifp->igmp_version, -                  group, -                  igmp->fd, -                  igmp->interface->name, -                  query_buf, -                  sizeof(query_buf), -                  0 /* num_sources_tosend */, -                  group->group_addr /* dst_addr */, -                  group->group_addr /* group_addr */, -                  pim_ifp->igmp_specific_query_max_response_time_dsec, -                  s_flag, -                  igmp->querier_robustness_variable, -                  igmp->querier_query_interval); +	struct igmp_sock *igmp; +	struct pim_interface *pim_ifp; +	long lmqc;      /* Last Member Query Count */ +	long lmqi_msec; /* Last Member Query Interval */ +	long lmqt_msec; /* Last Member Query Time */ +	int s_flag; +	int query_buf_size; + +	igmp = group->group_igmp_sock; +	pim_ifp = igmp->interface->info; + +	if (pim_ifp->igmp_version == 3) { +		query_buf_size = PIM_IGMP_BUFSIZE_WRITE; +	} else { +		query_buf_size = IGMP_V12_MSG_SIZE; +	} + +	char query_buf[query_buf_size]; + +	lmqc = igmp->querier_robustness_variable; +	lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; +	lmqt_msec = lmqc * lmqi_msec; + +	/* +	  RFC3376: 6.6.3.1. Building and Sending Group Specific Queries + +	  When transmitting a group specific query, if the group timer is +	  larger than LMQT, the "Suppress Router-Side Processing" bit is set +	  in the query message. +	*/ +	s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d", +			group_str, igmp->interface->name, s_flag, +			group->group_specific_query_retransmit_count); +	} + +	/* +	  RFC3376: 4.1.12. IP Destination Addresses for Queries + +	  Group-Specific and Group-and-Source-Specific Queries are sent with +	  an IP destination address equal to the multicast address of +	  interest. +	*/ + +	igmp_send_query(pim_ifp->igmp_version, group, igmp->fd, +			igmp->interface->name, query_buf, sizeof(query_buf), +			0 /* num_sources_tosend */, +			group->group_addr /* dst_addr */, +			group->group_addr /* group_addr */, +			pim_ifp->igmp_specific_query_max_response_time_dsec, +			s_flag, igmp->querier_robustness_variable, +			igmp->querier_query_interval);  }  /* @@ -1083,205 +1078,214 @@ static void group_retransmit_group(struct igmp_group *group)  static int group_retransmit_sources(struct igmp_group *group,  				    int send_with_sflag_set)  { -  struct igmp_sock     *igmp; -  struct pim_interface *pim_ifp; -  long                  lmqc;      /* Last Member Query Count */ -  long                  lmqi_msec; /* Last Member Query Interval */ -  long                  lmqt_msec; /* Last Member Query Time */ -  char                  query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */ -  char                  query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */ -  int                   query_buf1_max_sources; -  int                   query_buf2_max_sources; -  struct in_addr       *source_addr1; -  struct in_addr       *source_addr2; -  int                   num_sources_tosend1; -  int                   num_sources_tosend2; -  struct listnode      *src_node; -  struct igmp_source   *src; -  int                   num_retransmit_sources_left = 0; -   -  source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); -  source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); - -  igmp = group->group_igmp_sock; -  pim_ifp = igmp->interface->info; - -  lmqc      = igmp->querier_robustness_variable; -  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; -  lmqt_msec = lmqc * lmqi_msec; - -  /* Scan all group sources */ -  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { - -    /* Source has retransmission state? */ -    if (src->source_query_retransmit_count < 1) -      continue; - -    if (--src->source_query_retransmit_count > 0) { -      ++num_retransmit_sources_left; -    } - -    /* Copy source address into appropriate query buffer */ -    if (igmp_source_timer_remain_msec(src) > lmqt_msec) { -      *source_addr1 = src->source_addr; -      ++source_addr1; -    } -    else { -      *source_addr2 = src->source_addr; -      ++source_addr2; -    } - -  } -   -  num_sources_tosend1 = source_addr1 - (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); -  num_sources_tosend2 = source_addr2 - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d", -	       group_str, igmp->interface->name, -	       num_sources_tosend1, -	       num_sources_tosend2, -	       send_with_sflag_set, -	       num_retransmit_sources_left); -  } - -  if (num_sources_tosend1 > 0) { -    /* -      Send group-and-source-specific query with s_flag set and all -      sources with timers greater than LMQT. -    */ - -    if (send_with_sflag_set) { - -      query_buf1_max_sources = (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) >> 2; -      if (num_sources_tosend1 > query_buf1_max_sources) { -	char group_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -	zlog_warn("%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)", -		  __PRETTY_FUNCTION__, group_str, igmp->interface->name, -		  num_sources_tosend1, sizeof(query_buf1), query_buf1_max_sources); -      } -      else { -	/* -	  RFC3376: 4.1.12. IP Destination Addresses for Queries -       -	  Group-Specific and Group-and-Source-Specific Queries are sent with -	  an IP destination address equal to the multicast address of -	  interest. -	*/ -     -        igmp_send_query(pim_ifp->igmp_version, -                        group, -                        igmp->fd, -                        igmp->interface->name, -                        query_buf1, -                        sizeof(query_buf1), -                        num_sources_tosend1, -                        group->group_addr, -                        group->group_addr, -                        pim_ifp->igmp_specific_query_max_response_time_dsec, -                        1 /* s_flag */, -                        igmp->querier_robustness_variable, -                        igmp->querier_query_interval); -      } - -    } /* send_with_sflag_set */ - -  } - -  if (num_sources_tosend2 > 0) { -    /* -      Send group-and-source-specific query with s_flag clear and all -      sources with timers lower or equal to LMQT. -    */ -   -    query_buf2_max_sources = (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; -    if (num_sources_tosend2 > query_buf2_max_sources) { -      char group_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -      zlog_warn("%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)", -		__PRETTY_FUNCTION__, group_str, igmp->interface->name, -		num_sources_tosend2, sizeof(query_buf2), query_buf2_max_sources); -    } -    else { -      /* -	RFC3376: 4.1.12. IP Destination Addresses for Queries - -	Group-Specific and Group-and-Source-Specific Queries are sent with -	an IP destination address equal to the multicast address of -	interest. -      */ - -      igmp_send_query(pim_ifp->igmp_version, -                      group, -                      igmp->fd, -                      igmp->interface->name, -                      query_buf2, -                      sizeof(query_buf2), -                      num_sources_tosend2, -                      group->group_addr, -                      group->group_addr, -                      pim_ifp->igmp_specific_query_max_response_time_dsec, -                      0 /* s_flag */, -                      igmp->querier_robustness_variable, -                      igmp->querier_query_interval); -    } -  } - -  return num_retransmit_sources_left; +	struct igmp_sock *igmp; +	struct pim_interface *pim_ifp; +	long lmqc;      /* Last Member Query Count */ +	long lmqi_msec; /* Last Member Query Interval */ +	long lmqt_msec; /* Last Member Query Time */ +	char query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */ +	char query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */ +	int query_buf1_max_sources; +	int query_buf2_max_sources; +	struct in_addr *source_addr1; +	struct in_addr *source_addr2; +	int num_sources_tosend1; +	int num_sources_tosend2; +	struct listnode *src_node; +	struct igmp_source *src; +	int num_retransmit_sources_left = 0; + +	source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); +	source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); + +	igmp = group->group_igmp_sock; +	pim_ifp = igmp->interface->info; + +	lmqc = igmp->querier_robustness_variable; +	lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; +	lmqt_msec = lmqc * lmqi_msec; + +	/* Scan all group sources */ +	for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + +		/* Source has retransmission state? */ +		if (src->source_query_retransmit_count < 1) +			continue; + +		if (--src->source_query_retransmit_count > 0) { +			++num_retransmit_sources_left; +		} + +		/* Copy source address into appropriate query buffer */ +		if (igmp_source_timer_remain_msec(src) > lmqt_msec) { +			*source_addr1 = src->source_addr; +			++source_addr1; +		} else { +			*source_addr2 = src->source_addr; +			++source_addr2; +		} +	} + +	num_sources_tosend1 = +		source_addr1 +		- (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); +	num_sources_tosend2 = +		source_addr2 +		- (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d", +			group_str, igmp->interface->name, num_sources_tosend1, +			num_sources_tosend2, send_with_sflag_set, +			num_retransmit_sources_left); +	} + +	if (num_sources_tosend1 > 0) { +		/* +		  Send group-and-source-specific query with s_flag set and all +		  sources with timers greater than LMQT. +		*/ + +		if (send_with_sflag_set) { + +			query_buf1_max_sources = +				(sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) +				>> 2; +			if (num_sources_tosend1 > query_buf1_max_sources) { +				char group_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<group?>", group->group_addr, +					       group_str, sizeof(group_str)); +				zlog_warn( +					"%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)", +					__PRETTY_FUNCTION__, group_str, +					igmp->interface->name, +					num_sources_tosend1, sizeof(query_buf1), +					query_buf1_max_sources); +			} else { +				/* +				  RFC3376: 4.1.12. IP Destination Addresses for +				  Queries + +				  Group-Specific and Group-and-Source-Specific +				  Queries are sent with +				  an IP destination address equal to the +				  multicast address of +				  interest. +				*/ + +				igmp_send_query( +					pim_ifp->igmp_version, group, igmp->fd, +					igmp->interface->name, query_buf1, +					sizeof(query_buf1), num_sources_tosend1, +					group->group_addr, group->group_addr, +					pim_ifp->igmp_specific_query_max_response_time_dsec, +					1 /* s_flag */, +					igmp->querier_robustness_variable, +					igmp->querier_query_interval); +			} + +		} /* send_with_sflag_set */ +	} + +	if (num_sources_tosend2 > 0) { +		/* +		  Send group-and-source-specific query with s_flag clear and all +		  sources with timers lower or equal to LMQT. +		*/ + +		query_buf2_max_sources = +			(sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; +		if (num_sources_tosend2 > query_buf2_max_sources) { +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", group->group_addr, group_str, +				       sizeof(group_str)); +			zlog_warn( +				"%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)", +				__PRETTY_FUNCTION__, group_str, +				igmp->interface->name, num_sources_tosend2, +				sizeof(query_buf2), query_buf2_max_sources); +		} else { +			/* +			  RFC3376: 4.1.12. IP Destination Addresses for Queries + +			  Group-Specific and Group-and-Source-Specific Queries +			  are sent with +			  an IP destination address equal to the multicast +			  address of +			  interest. +			*/ + +			igmp_send_query( +				pim_ifp->igmp_version, group, igmp->fd, +				igmp->interface->name, query_buf2, +				sizeof(query_buf2), num_sources_tosend2, +				group->group_addr, group->group_addr, +				pim_ifp->igmp_specific_query_max_response_time_dsec, +				0 /* s_flag */, +				igmp->querier_robustness_variable, +				igmp->querier_query_interval); +		} +	} + +	return num_retransmit_sources_left;  }  static int igmp_group_retransmit(struct thread *t)  { -  struct igmp_group *group; -  int num_retransmit_sources_left; -  int send_with_sflag_set; /* boolean */ - -  group = THREAD_ARG(t); - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("group_retransmit_timer: group %s on %s", -	       group_str, group->group_igmp_sock->interface->name); -  } - -  /* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */ -  if (group->group_specific_query_retransmit_count > 0) { - -    /* Retransmit group-specific queries (RFC3376: 6.6.3.1) */ -    group_retransmit_group(group); -    --group->group_specific_query_retransmit_count; - -    /* -      RFC3376: 6.6.3.2 -      If a group specific query is scheduled to be transmitted at the -      same time as a group and source specific query for the same group, -      then transmission of the group and source specific message with the -      "Suppress Router-Side Processing" bit set may be suppressed. -    */ -    send_with_sflag_set = 0; /* boolean=false */ -  } -  else { -    send_with_sflag_set = 1; /* boolean=true */ -  } - -  /* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */ -  num_retransmit_sources_left = group_retransmit_sources(group, -							 send_with_sflag_set); - -  /* -    Keep group retransmit timer running if there is any retransmit -    counter pending -  */ -  if ((num_retransmit_sources_left > 0) || -      (group->group_specific_query_retransmit_count > 0)) { -    group_retransmit_timer_on(group); -  } - -  return 0; +	struct igmp_group *group; +	int num_retransmit_sources_left; +	int send_with_sflag_set; /* boolean */ + +	group = THREAD_ARG(t); + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug("group_retransmit_timer: group %s on %s", group_str, +			   group->group_igmp_sock->interface->name); +	} + +	/* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */ +	if (group->group_specific_query_retransmit_count > 0) { + +		/* Retransmit group-specific queries (RFC3376: 6.6.3.1) */ +		group_retransmit_group(group); +		--group->group_specific_query_retransmit_count; + +		/* +		  RFC3376: 6.6.3.2 +		  If a group specific query is scheduled to be transmitted at +		  the +		  same time as a group and source specific query for the same +		  group, +		  then transmission of the group and source specific message +		  with the +		  "Suppress Router-Side Processing" bit set may be suppressed. +		*/ +		send_with_sflag_set = 0; /* boolean=false */ +	} else { +		send_with_sflag_set = 1; /* boolean=true */ +	} + +	/* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */ +	num_retransmit_sources_left = +		group_retransmit_sources(group, send_with_sflag_set); + +	/* +	  Keep group retransmit timer running if there is any retransmit +	  counter pending +	*/ +	if ((num_retransmit_sources_left > 0) +	    || (group->group_specific_query_retransmit_count > 0)) { +		group_retransmit_timer_on(group); +	} + +	return 0;  }  /* @@ -1291,42 +1295,42 @@ static int igmp_group_retransmit(struct thread *t)  */  static void group_retransmit_timer_on(struct igmp_group *group)  { -  struct igmp_sock     *igmp; -  struct pim_interface *pim_ifp; -  long                  lmqi_msec; /* Last Member Query Interval */ - -  /* if group retransmit timer is running, do nothing */ -  if (group->t_group_query_retransmit_timer) { -    return; -  } - -  igmp = group->group_igmp_sock; -  pim_ifp = igmp->interface->info; - -  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("Scheduling %ld.%03ld sec retransmit timer for group %s on %s", -	       lmqi_msec / 1000, -	       lmqi_msec % 1000, -	       group_str, -	       igmp->interface->name); -  } - -  thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec, -                        &group->t_group_query_retransmit_timer); +	struct igmp_sock *igmp; +	struct pim_interface *pim_ifp; +	long lmqi_msec; /* Last Member Query Interval */ + +	/* if group retransmit timer is running, do nothing */ +	if (group->t_group_query_retransmit_timer) { +		return; +	} + +	igmp = group->group_igmp_sock; +	pim_ifp = igmp->interface->info; + +	lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"Scheduling %ld.%03ld sec retransmit timer for group %s on %s", +			lmqi_msec / 1000, lmqi_msec % 1000, group_str, +			igmp->interface->name); +	} + +	thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec, +			      &group->t_group_query_retransmit_timer);  }  static long igmp_group_timer_remain_msec(struct igmp_group *group)  { -  return pim_time_timer_remain_msec(group->t_group_timer); +	return pim_time_timer_remain_msec(group->t_group_timer);  }  static long igmp_source_timer_remain_msec(struct igmp_source *source)  { -  return pim_time_timer_remain_msec(source->t_source_timer); +	return pim_time_timer_remain_msec(source->t_source_timer);  }  /* @@ -1334,21 +1338,22 @@ static long igmp_source_timer_remain_msec(struct igmp_source *source)  */  static void group_query_send(struct igmp_group *group)  { -  long              lmqc;    /* Last Member Query Count */ +	long lmqc; /* Last Member Query Count */ -  lmqc = group->group_igmp_sock->querier_robustness_variable; +	lmqc = group->group_igmp_sock->querier_robustness_variable; -  /* lower group timer to lmqt */ -  igmp_group_timer_lower_to_lmqt(group); +	/* lower group timer to lmqt */ +	igmp_group_timer_lower_to_lmqt(group); -  /* reset retransmission counter */ -  group->group_specific_query_retransmit_count = lmqc; +	/* reset retransmission counter */ +	group->group_specific_query_retransmit_count = lmqc; -  /* immediately send group specific query (decrease retransmit counter by 1)*/ -  group_retransmit_group(group); +	/* immediately send group specific query (decrease retransmit counter by +	 * 1)*/ +	group_retransmit_group(group); -  /* make sure group retransmit timer is running */ -  group_retransmit_timer_on(group); +	/* make sure group retransmit timer is running */ +	group_retransmit_timer_on(group);  }  /* @@ -1357,612 +1362,674 @@ static void group_query_send(struct igmp_group *group)  static void source_query_send_by_flag(struct igmp_group *group,  				      int num_sources_tosend)  { -  struct igmp_sock     *igmp; -  struct pim_interface *pim_ifp; -  struct listnode      *src_node; -  struct igmp_source   *src; -  long                  lmqc;      /* Last Member Query Count */ -  long                  lmqi_msec; /* Last Member Query Interval */ -  long                  lmqt_msec; /* Last Member Query Time */ - -  zassert(num_sources_tosend > 0); - -  igmp = group->group_igmp_sock; -  pim_ifp = igmp->interface->info; - -  lmqc      = igmp->querier_robustness_variable; -  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; -  lmqt_msec = lmqc * lmqi_msec; - -  /* -    RFC3376: 6.6.3.2. Building and Sending Group and Source Specific Queries - -    (...) for each of the sources in X of group G, with source timer larger -    than LMQT: -    o Set number of retransmissions for each source to [Last Member -    Query Count]. -    o Lower source timer to LMQT. -  */ -  for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { -    if (IGMP_SOURCE_TEST_SEND(src->source_flags)) { -      /* source "src" in X of group G */ -      if (igmp_source_timer_remain_msec(src) > lmqt_msec) { -	src->source_query_retransmit_count = lmqc; -	igmp_source_timer_lower_to_lmqt(src); -      } -    } -  } - -  /* send group-and-source specific queries */ -  group_retransmit_sources(group, 1 /* send_with_sflag_set=true */); - -  /* make sure group retransmit timer is running */ -  group_retransmit_timer_on(group); +	struct igmp_sock *igmp; +	struct pim_interface *pim_ifp; +	struct listnode *src_node; +	struct igmp_source *src; +	long lmqc;      /* Last Member Query Count */ +	long lmqi_msec; /* Last Member Query Interval */ +	long lmqt_msec; /* Last Member Query Time */ + +	zassert(num_sources_tosend > 0); + +	igmp = group->group_igmp_sock; +	pim_ifp = igmp->interface->info; + +	lmqc = igmp->querier_robustness_variable; +	lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; +	lmqt_msec = lmqc * lmqi_msec; + +	/* +	  RFC3376: 6.6.3.2. Building and Sending Group and Source Specific +	  Queries + +	  (...) for each of the sources in X of group G, with source timer +	  larger +	  than LMQT: +	  o Set number of retransmissions for each source to [Last Member +	  Query Count]. +	  o Lower source timer to LMQT. +	*/ +	for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { +		if (IGMP_SOURCE_TEST_SEND(src->source_flags)) { +			/* source "src" in X of group G */ +			if (igmp_source_timer_remain_msec(src) > lmqt_msec) { +				src->source_query_retransmit_count = lmqc; +				igmp_source_timer_lower_to_lmqt(src); +			} +		} +	} + +	/* send group-and-source specific queries */ +	group_retransmit_sources(group, 1 /* send_with_sflag_set=true */); + +	/* make sure group retransmit timer is running */ +	group_retransmit_timer_on(group);  } -static void block_excl(struct igmp_group *group, -		       int num_sources, struct in_addr *sources) +static void block_excl(struct igmp_group *group, int num_sources, +		       struct in_addr *sources)  { -  int num_sources_tosend = 0; -  int i; - -  /* 1. clear off SEND flag from all known sources (X,Y) */ -  source_clear_send_flag(group->group_source_list); - -  /* 2. scan received sources (A) */ -  for (i = 0; i < num_sources; ++i) { -    struct igmp_source *source; -    struct in_addr     *src_addr; -     -    src_addr = sources + i; -     -    /* lookup reported source (A) in known sources (X,Y) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (!source) { -      /* 3: if not found, create source with Group Timer: (A-X-Y)=Group Timer */ -      long group_timer_msec; -      source = source_new(group, *src_addr); -      if (!source) { -	/* ugh, internal malloc failure, skip source */ -	continue; -      } - -      zassert(!source->t_source_timer); /* timer == 0 */ -      group_timer_msec = igmp_group_timer_remain_msec(group); -      igmp_source_timer_on(group, source, group_timer_msec); -      zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ -    } - -    if (source->t_source_timer) { -      /* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */ -      IGMP_SOURCE_DO_SEND(source->source_flags); -      ++num_sources_tosend; -    } -  } -  -  /* 5. send sources marked with SEND flag: Q(G,A-Y) */ -  if (num_sources_tosend > 0) { -    source_query_send_by_flag(group, num_sources_tosend); -  } +	int num_sources_tosend = 0; +	int i; + +	/* 1. clear off SEND flag from all known sources (X,Y) */ +	source_clear_send_flag(group->group_source_list); + +	/* 2. scan received sources (A) */ +	for (i = 0; i < num_sources; ++i) { +		struct igmp_source *source; +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* lookup reported source (A) in known sources (X,Y) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (!source) { +			/* 3: if not found, create source with Group Timer: +			 * (A-X-Y)=Group Timer */ +			long group_timer_msec; +			source = source_new(group, *src_addr); +			if (!source) { +				/* ugh, internal malloc failure, skip source */ +				continue; +			} + +			zassert(!source->t_source_timer); /* timer == 0 */ +			group_timer_msec = igmp_group_timer_remain_msec(group); +			igmp_source_timer_on(group, source, group_timer_msec); +			zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ +		} + +		if (source->t_source_timer) { +			/* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */ +			IGMP_SOURCE_DO_SEND(source->source_flags); +			++num_sources_tosend; +		} +	} + +	/* 5. send sources marked with SEND flag: Q(G,A-Y) */ +	if (num_sources_tosend > 0) { +		source_query_send_by_flag(group, num_sources_tosend); +	}  } -static void block_incl(struct igmp_group *group, -		       int num_sources, struct in_addr *sources) +static void block_incl(struct igmp_group *group, int num_sources, +		       struct in_addr *sources)  { -  int num_sources_tosend = 0; -  int i; - -  /* 1. clear off SEND flag from all known sources (B) */ -  source_clear_send_flag(group->group_source_list); - -  /* 2. scan received sources (A) */ -  for (i = 0; i < num_sources; ++i) { -    struct igmp_source *source; -    struct in_addr     *src_addr; -     -    src_addr = sources + i; -     -    /* lookup reported source (A) in known sources (B) */ -    source = igmp_find_source_by_addr(group, *src_addr); -    if (source) { -      /* 3. if found (A*B), mark SEND flag: Q(G,A*B) */ -      IGMP_SOURCE_DO_SEND(source->source_flags); -      ++num_sources_tosend; -    } -  }  -  -  /* 4. send sources marked with SEND flag: Q(G,A*B) */ -  if (num_sources_tosend > 0) { -    source_query_send_by_flag(group, num_sources_tosend); -  } +	int num_sources_tosend = 0; +	int i; + +	/* 1. clear off SEND flag from all known sources (B) */ +	source_clear_send_flag(group->group_source_list); + +	/* 2. scan received sources (A) */ +	for (i = 0; i < num_sources; ++i) { +		struct igmp_source *source; +		struct in_addr *src_addr; + +		src_addr = sources + i; + +		/* lookup reported source (A) in known sources (B) */ +		source = igmp_find_source_by_addr(group, *src_addr); +		if (source) { +			/* 3. if found (A*B), mark SEND flag: Q(G,A*B) */ +			IGMP_SOURCE_DO_SEND(source->source_flags); +			++num_sources_tosend; +		} +	} + +	/* 4. send sources marked with SEND flag: Q(G,A*B) */ +	if (num_sources_tosend > 0) { +		source_query_send_by_flag(group, num_sources_tosend); +	}  }  void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from, -			 struct in_addr group_addr, -			 int num_sources, struct in_addr *sources) +			 struct in_addr group_addr, int num_sources, +			 struct in_addr *sources)  { -  struct interface *ifp = igmp->interface; -  struct igmp_group *group; - -  on_trace(__PRETTY_FUNCTION__, -	   ifp, from, group_addr, num_sources, sources); - -  /* non-existant group is created as INCLUDE {empty} */ -  group = igmp_add_group_by_addr(igmp, group_addr); -  if (!group) { -    return; -  } - -  if (group->group_filtermode_isexcl) { -    /* EXCLUDE mode */ -    block_excl(group, num_sources, sources); -  } -  else { -    /* INCLUDE mode */ -    block_incl(group, num_sources, sources); -  } +	struct interface *ifp = igmp->interface; +	struct igmp_group *group; + +	on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, +		 sources); + +	/* non-existant group is created as INCLUDE {empty} */ +	group = igmp_add_group_by_addr(igmp, group_addr); +	if (!group) { +		return; +	} + +	if (group->group_filtermode_isexcl) { +		/* EXCLUDE mode */ +		block_excl(group, num_sources, sources); +	} else { +		/* INCLUDE mode */ +		block_incl(group, num_sources, sources); +	}  }  void igmp_group_timer_lower_to_lmqt(struct igmp_group *group)  { -  struct igmp_sock     *igmp; -  struct interface     *ifp; -  struct pim_interface *pim_ifp; -  char                 *ifname; -  int   lmqi_dsec; /* Last Member Query Interval */ -  int   lmqc;      /* Last Member Query Count */ -  int   lmqt_msec; /* Last Member Query Time */ - -  /* -    RFC 3376: 6.2.2. Definition of Group Timers -     -    The group timer is only used when a group is in EXCLUDE mode and -    it represents the time for the *filter-mode* of the group to -    expire and switch to INCLUDE mode. -  */ -  if (!group->group_filtermode_isexcl) { -    return; -  } - -  igmp    = group->group_igmp_sock; -  ifp     = igmp->interface; -  pim_ifp = ifp->info; -  ifname  = ifp->name; - -  lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; -  lmqc      = igmp->querier_robustness_variable; -  lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    zlog_debug("%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", -	       __PRETTY_FUNCTION__, -	       group_str, ifname, -	       lmqc, lmqi_dsec, lmqt_msec); -  } - -  zassert(group->group_filtermode_isexcl); - -  igmp_group_timer_on(group, lmqt_msec, ifname); +	struct igmp_sock *igmp; +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	char *ifname; +	int lmqi_dsec; /* Last Member Query Interval */ +	int lmqc;      /* Last Member Query Count */ +	int lmqt_msec; /* Last Member Query Time */ + +	/* +	  RFC 3376: 6.2.2. Definition of Group Timers + +	  The group timer is only used when a group is in EXCLUDE mode and +	  it represents the time for the *filter-mode* of the group to +	  expire and switch to INCLUDE mode. +	*/ +	if (!group->group_filtermode_isexcl) { +		return; +	} + +	igmp = group->group_igmp_sock; +	ifp = igmp->interface; +	pim_ifp = ifp->info; +	ifname = ifp->name; + +	lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; +	lmqc = igmp->querier_robustness_variable; +	lmqt_msec = PIM_IGMP_LMQT_MSEC( +		lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", +			__PRETTY_FUNCTION__, group_str, ifname, lmqc, lmqi_dsec, +			lmqt_msec); +	} + +	zassert(group->group_filtermode_isexcl); + +	igmp_group_timer_on(group, lmqt_msec, ifname);  }  void igmp_source_timer_lower_to_lmqt(struct igmp_source *source)  { -  struct igmp_group    *group; -  struct igmp_sock     *igmp; -  struct interface     *ifp; -  struct pim_interface *pim_ifp; -  char                 *ifname; -  int   lmqi_dsec; /* Last Member Query Interval */ -  int   lmqc;      /* Last Member Query Count */ -  int   lmqt_msec; /* Last Member Query Time */ - -  group   = source->source_group; -  igmp    = group->group_igmp_sock; -  ifp     = igmp->interface; -  pim_ifp = ifp->info; -  ifname  = ifp->name; - -  lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; -  lmqc      = igmp->querier_robustness_variable; -  lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ - -  if (PIM_DEBUG_IGMP_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); -    zlog_debug("%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", -	       __PRETTY_FUNCTION__, -	       group_str, source_str, ifname, -	       lmqc, lmqi_dsec, lmqt_msec); -  } - -  igmp_source_timer_on(group, source, lmqt_msec); +	struct igmp_group *group; +	struct igmp_sock *igmp; +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	char *ifname; +	int lmqi_dsec; /* Last Member Query Interval */ +	int lmqc;      /* Last Member Query Count */ +	int lmqt_msec; /* Last Member Query Time */ + +	group = source->source_group; +	igmp = group->group_igmp_sock; +	ifp = igmp->interface; +	pim_ifp = ifp->info; +	ifname = ifp->name; + +	lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; +	lmqc = igmp->querier_robustness_variable; +	lmqt_msec = PIM_IGMP_LMQT_MSEC( +		lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ + +	if (PIM_DEBUG_IGMP_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", group->group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<source?>", source->source_addr, source_str, +			       sizeof(source_str)); +		zlog_debug( +			"%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", +			__PRETTY_FUNCTION__, group_str, source_str, ifname, +			lmqc, lmqi_dsec, lmqt_msec); +	} + +	igmp_source_timer_on(group, source, lmqt_msec);  } -void -igmp_v3_send_query (struct igmp_group *group, -                    int fd, -                    const char *ifname, -                    char *query_buf, -                    int query_buf_size, -                    int num_sources, -                    struct in_addr dst_addr, -                    struct in_addr group_addr, -                    int query_max_response_time_dsec, -                    uint8_t s_flag, -                    uint8_t querier_robustness_variable, -                    uint16_t querier_query_interval) +void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, +			char *query_buf, int query_buf_size, int num_sources, +			struct in_addr dst_addr, struct in_addr group_addr, +			int query_max_response_time_dsec, uint8_t s_flag, +			uint8_t querier_robustness_variable, +			uint16_t querier_query_interval)  { -  ssize_t             msg_size; -  uint8_t             max_resp_code; -  uint8_t             qqic; -  ssize_t             sent; -  struct sockaddr_in  to; -  socklen_t           tolen; -  uint16_t            checksum; - -  zassert(num_sources >= 0); - -  msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2); -  if (msg_size > query_buf_size) { -    zlog_err("%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d", -	     __FILE__, __PRETTY_FUNCTION__, -	     msg_size, query_buf_size); -    return; -  } - -  s_flag = PIM_FORCE_BOOLEAN(s_flag); -  zassert((s_flag == 0) || (s_flag == 1)); - -  max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); -  qqic          = igmp_msg_encode16to8(querier_query_interval); - -  /* -    RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) - -    If non-zero, the QRV field contains the [Robustness Variable] -    value used by the querier, i.e., the sender of the Query.  If the -    querier's [Robustness Variable] exceeds 7, the maximum value of -    the QRV field, the QRV is set to zero. -  */ -  if (querier_robustness_variable > 7) { -    querier_robustness_variable = 0; -  } - -  query_buf[0]                                         = PIM_IGMP_MEMBERSHIP_QUERY; -  query_buf[1]                                         = max_resp_code; -  *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET)   = 0; /* for computing checksum */ -  memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); - -  query_buf[8]                                         = (s_flag << 3) | querier_robustness_variable; -  query_buf[9]                                         = qqic; -  *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = htons(num_sources); - -  checksum = in_cksum(query_buf, msg_size); -  *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; - -  if (PIM_DEBUG_IGMP_PACKETS) { -    char dst_str[INET_ADDRSTRLEN]; -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); -    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); -    zlog_debug("Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", -	       dst_str, ifname, group_str, -               num_sources, msg_size, s_flag, querier_robustness_variable, -               querier_query_interval, qqic); -  } - -  memset(&to, 0, sizeof(to)); -  to.sin_family = AF_INET; -  to.sin_addr = dst_addr; -  tolen = sizeof(to); - -  sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, -                (struct sockaddr *)&to, tolen); -  if (sent != (ssize_t) msg_size) { -    char dst_str[INET_ADDRSTRLEN]; -    char group_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); -    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); -    if (sent < 0) { -      zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", -		dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); -    } -    else { -      zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", -		dst_str, ifname, group_str, msg_size, sent); -    } -    return; -  } - -  /* -    s_flag sanity test: s_flag must be set for general queries - -    RFC 3376: 6.6.1. Timer Updates - -    When a router sends or receives a query with a clear Suppress -    Router-Side Processing flag, it must update its timers to reflect -    the correct timeout values for the group or sources being queried. - -    General queries don't trigger timer update. -  */ -  if (!s_flag) { -    /* general query? */ -    if (PIM_INADDR_IS_ANY(group_addr)) { -      char dst_str[INET_ADDRSTRLEN]; -      char group_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); -      pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); -      zlog_warn("%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!", -		__PRETTY_FUNCTION__, -		dst_str, ifname, group_str, num_sources); -    } -  } +	ssize_t msg_size; +	uint8_t max_resp_code; +	uint8_t qqic; +	ssize_t sent; +	struct sockaddr_in to; +	socklen_t tolen; +	uint16_t checksum; + +	zassert(num_sources >= 0); + +	msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2); +	if (msg_size > query_buf_size) { +		zlog_err( +			"%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d", +			__FILE__, __PRETTY_FUNCTION__, msg_size, +			query_buf_size); +		return; +	} + +	s_flag = PIM_FORCE_BOOLEAN(s_flag); +	zassert((s_flag == 0) || (s_flag == 1)); + +	max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); +	qqic = igmp_msg_encode16to8(querier_query_interval); + +	/* +	  RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) + +	  If non-zero, the QRV field contains the [Robustness Variable] +	  value used by the querier, i.e., the sender of the Query.  If the +	  querier's [Robustness Variable] exceeds 7, the maximum value of +	  the QRV field, the QRV is set to zero. +	*/ +	if (querier_robustness_variable > 7) { +		querier_robustness_variable = 0; +	} + +	query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; +	query_buf[1] = max_resp_code; +	*(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = +		0; /* for computing checksum */ +	memcpy(query_buf + 4, &group_addr, sizeof(struct in_addr)); + +	query_buf[8] = (s_flag << 3) | querier_robustness_variable; +	query_buf[9] = qqic; +	*(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = +		htons(num_sources); + +	checksum = in_cksum(query_buf, msg_size); +	*(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; + +	if (PIM_DEBUG_IGMP_PACKETS) { +		char dst_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); +		pim_inet4_dump("<group?>", group_addr, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", +			dst_str, ifname, group_str, num_sources, msg_size, +			s_flag, querier_robustness_variable, +			querier_query_interval, qqic); +	} + +	memset(&to, 0, sizeof(to)); +	to.sin_family = AF_INET; +	to.sin_addr = dst_addr; +	tolen = sizeof(to); + +	sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, +		      (struct sockaddr *)&to, tolen); +	if (sent != (ssize_t)msg_size) { +		char dst_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str)); +		pim_inet4_dump("<group?>", group_addr, group_str, +			       sizeof(group_str)); +		if (sent < 0) { +			zlog_warn( +				"Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", +				dst_str, ifname, group_str, msg_size, errno, +				safe_strerror(errno)); +		} else { +			zlog_warn( +				"Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", +				dst_str, ifname, group_str, msg_size, sent); +		} +		return; +	} + +	/* +	  s_flag sanity test: s_flag must be set for general queries + +	  RFC 3376: 6.6.1. Timer Updates + +	  When a router sends or receives a query with a clear Suppress +	  Router-Side Processing flag, it must update its timers to reflect +	  the correct timeout values for the group or sources being queried. + +	  General queries don't trigger timer update. +	*/ +	if (!s_flag) { +		/* general query? */ +		if (PIM_INADDR_IS_ANY(group_addr)) { +			char dst_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<dst?>", dst_addr, dst_str, +				       sizeof(dst_str)); +			pim_inet4_dump("<group?>", group_addr, group_str, +				       sizeof(group_str)); +			zlog_warn( +				"%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!", +				__PRETTY_FUNCTION__, dst_str, ifname, group_str, +				num_sources); +		} +	}  } -void -igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, char *igmp_msg) +void igmp_v3_recv_query(struct igmp_sock *igmp, const char *from_str, +			char *igmp_msg)  { -  struct interface     *ifp; -  struct pim_interface *pim_ifp; -  struct in_addr        group_addr; -  uint8_t resv_s_qrv = 0; -  uint8_t s_flag = 0; -  uint8_t qrv = 0; -  int     i; - -  memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); -  ifp = igmp->interface; -  pim_ifp = ifp->info; - -  /* -   * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) -   * -   * Routers adopt the QRV value from the most recently received Query -   * as their own [Robustness Variable] value, unless that most -   * recently received QRV was zero, in which case the receivers use -   * the default [Robustness Variable] value specified in section 8.1 -   * or a statically configured value. -   */ -  resv_s_qrv = igmp_msg[8]; -  qrv = 7 & resv_s_qrv; -  igmp->querier_robustness_variable = qrv ? qrv : pim_ifp->igmp_default_robustness_variable; - -  /* -   * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) -   * -   * Multicast routers that are not the current querier adopt the QQI -   * value from the most recently received Query as their own [Query -   * Interval] value, unless that most recently received QQI was zero, -   * in which case the receiving routers use the default. -   */ -  if (igmp->t_other_querier_timer) { -    /* other querier present */ -    uint8_t  qqic; -    uint16_t qqi; -    qqic = igmp_msg[9]; -    qqi = igmp_msg_decode8to16(qqic); -    igmp->querier_query_interval = qqi ? qqi : pim_ifp->igmp_default_query_interval; - -    if (PIM_DEBUG_IGMP_TRACE) { -      char ifaddr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); -      zlog_debug("Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", -                 ifaddr_str, -                 qqi ? "recv-non-default" : "default", -                 igmp->querier_query_interval, -                 qqic, -                 from_str); -    } -  } - -  /* -   * RFC 3376: 6.6.1. Timer Updates -   * -   * When a router sends or receives a query with a clear Suppress -   * Router-Side Processing flag, it must update its timers to reflect -   * the correct timeout values for the group or sources being queried. -   * -   * General queries don't trigger timer update. -   */ -  s_flag = (1 << 3) & resv_s_qrv; - -  if (!s_flag) { -    /* s_flag is clear */ - -    if (PIM_INADDR_IS_ANY(group_addr)) { -      /* this is a general query */ -      /* log that general query should have the s_flag set */ -      zlog_warn("General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear", -                from_str, ifp->name); -    } else { -      struct igmp_group *group; - -      /* this is a non-general query: perform timer updates */ - -      group = find_group_by_addr(igmp, group_addr); -      if (group) { -        int recv_num_sources = ntohs(*(uint16_t *)(igmp_msg + IGMP_V3_NUMSOURCES_OFFSET)); - -        /* -         * RFC 3376: 6.6.1. Timer Updates -         * Query Q(G,A): Source Timer for sources in A are lowered to LMQT -         * Query Q(G): Group Timer is lowered to LMQT -         */ -        if (recv_num_sources < 1) { -          /* Query Q(G): Group Timer is lowered to LMQT */ - -          igmp_group_timer_lower_to_lmqt(group); -        } else { -          /* Query Q(G,A): Source Timer for sources in A are lowered to LMQT */ - -          /* Scan sources in query and lower their timers to LMQT */ -          struct in_addr *sources = (struct in_addr *)(igmp_msg + IGMP_V3_SOURCES_OFFSET); -          for (i = 0; i < recv_num_sources; ++i) { -            struct in_addr src_addr; -            struct igmp_source *src; -            memcpy(&src_addr, sources + i, sizeof(struct in_addr)); -            src = igmp_find_source_by_addr(group, src_addr); -            if (src) { -              igmp_source_timer_lower_to_lmqt(src); -            } -          } -        } -      } else { -        char group_str[INET_ADDRSTRLEN]; -        pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); -        zlog_warn("IGMP query v3 from %s on %s: could not find group %s for timer update", -                  from_str, ifp->name, group_str); -      } -    } -  } /* s_flag is clear: timer updates */ +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	struct in_addr group_addr; +	uint8_t resv_s_qrv = 0; +	uint8_t s_flag = 0; +	uint8_t qrv = 0; +	int i; + +	memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); +	ifp = igmp->interface; +	pim_ifp = ifp->info; + +	/* +	 * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) +	 * +	 * Routers adopt the QRV value from the most recently received Query +	 * as their own [Robustness Variable] value, unless that most +	 * recently received QRV was zero, in which case the receivers use +	 * the default [Robustness Variable] value specified in section 8.1 +	 * or a statically configured value. +	 */ +	resv_s_qrv = igmp_msg[8]; +	qrv = 7 & resv_s_qrv; +	igmp->querier_robustness_variable = +		qrv ? qrv : pim_ifp->igmp_default_robustness_variable; + +	/* +	 * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) +	 * +	 * Multicast routers that are not the current querier adopt the QQI +	 * value from the most recently received Query as their own [Query +	 * Interval] value, unless that most recently received QQI was zero, +	 * in which case the receiving routers use the default. +	 */ +	if (igmp->t_other_querier_timer) { +		/* other querier present */ +		uint8_t qqic; +		uint16_t qqi; +		qqic = igmp_msg[9]; +		qqi = igmp_msg_decode8to16(qqic); +		igmp->querier_query_interval = +			qqi ? qqi : pim_ifp->igmp_default_query_interval; + +		if (PIM_DEBUG_IGMP_TRACE) { +			char ifaddr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, +				       sizeof(ifaddr_str)); +			zlog_debug( +				"Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", +				ifaddr_str, +				qqi ? "recv-non-default" : "default", +				igmp->querier_query_interval, qqic, from_str); +		} +	} + +	/* +	 * RFC 3376: 6.6.1. Timer Updates +	 * +	 * When a router sends or receives a query with a clear Suppress +	 * Router-Side Processing flag, it must update its timers to reflect +	 * the correct timeout values for the group or sources being queried. +	 * +	 * General queries don't trigger timer update. +	 */ +	s_flag = (1 << 3) & resv_s_qrv; + +	if (!s_flag) { +		/* s_flag is clear */ + +		if (PIM_INADDR_IS_ANY(group_addr)) { +			/* this is a general query */ +			/* log that general query should have the s_flag set */ +			zlog_warn( +				"General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear", +				from_str, ifp->name); +		} else { +			struct igmp_group *group; + +			/* this is a non-general query: perform timer updates */ + +			group = find_group_by_addr(igmp, group_addr); +			if (group) { +				int recv_num_sources = ntohs(*( +					uint16_t +						*)(igmp_msg +						   + IGMP_V3_NUMSOURCES_OFFSET)); + +				/* +				 * RFC 3376: 6.6.1. Timer Updates +				 * Query Q(G,A): Source Timer for sources in A +				 * are lowered to LMQT +				 * Query Q(G): Group Timer is lowered to LMQT +				 */ +				if (recv_num_sources < 1) { +					/* Query Q(G): Group Timer is lowered to +					 * LMQT */ + +					igmp_group_timer_lower_to_lmqt(group); +				} else { +					/* Query Q(G,A): Source Timer for +					 * sources in A are lowered to LMQT */ + +					/* Scan sources in query and lower their +					 * timers to LMQT */ +					struct in_addr *sources = +						(struct in_addr +							 *)(igmp_msg +							    + IGMP_V3_SOURCES_OFFSET); +					for (i = 0; i < recv_num_sources; ++i) { +						struct in_addr src_addr; +						struct igmp_source *src; +						memcpy(&src_addr, sources + i, +						       sizeof(struct in_addr)); +						src = igmp_find_source_by_addr( +							group, src_addr); +						if (src) { +							igmp_source_timer_lower_to_lmqt( +								src); +						} +					} +				} +			} else { +				char group_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<group?>", group_addr, +					       group_str, sizeof(group_str)); +				zlog_warn( +					"IGMP query v3 from %s on %s: could not find group %s for timer update", +					from_str, ifp->name, group_str); +			} +		} +	} /* s_flag is clear: timer updates */  } -int -igmp_v3_recv_report (struct igmp_sock *igmp, -                     struct in_addr from, const char *from_str, -                     char *igmp_msg, int igmp_msg_len) +int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, +			const char *from_str, char *igmp_msg, int igmp_msg_len)  { -  uint16_t          recv_checksum; -  uint16_t          checksum; -  int               num_groups; -  uint8_t          *group_record; -  uint8_t          *report_pastend = (uint8_t *) igmp_msg + igmp_msg_len; -  struct interface *ifp = igmp->interface; -  int               i; -  int               local_ncb = 0; - -  if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { -    zlog_warn("Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", -              from_str, ifp->name, igmp_msg_len, IGMP_V3_MSG_MIN_SIZE); -    return -1; -  } - -  recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); - -  /* for computing checksum */ -  *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; - -  checksum = in_cksum(igmp_msg, igmp_msg_len); -  if (checksum != recv_checksum) { -    zlog_warn("Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", -              from_str, ifp->name, recv_checksum, checksum); -    return -1; -  } - -  num_groups = ntohs(*(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); -  if (num_groups < 1) { -    zlog_warn("Recv IGMP report v3 from %s on %s: missing group records", -              from_str, ifp->name); -    return -1; -  } - -  if (PIM_DEBUG_IGMP_PACKETS) { -    zlog_debug("Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", -               from_str, ifp->name, igmp_msg_len, checksum, num_groups); -  } - -  group_record = (uint8_t *) igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; - -  /* Scan groups */ -  for (i = 0; i < num_groups; ++i) { -    struct in_addr  rec_group; -    uint8_t        *sources; -    uint8_t        *src; -    int             rec_type; -    int             rec_auxdatalen; -    int             rec_num_sources; -    int             j; -    struct prefix   lncb; -    struct prefix   g; - -    if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) > report_pastend) { -      zlog_warn("Recv IGMP report v3 from %s on %s: group record beyond report end", -                from_str, ifp->name); -      return -1; -    } - -    rec_type        = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; -    rec_auxdatalen  = group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; -    rec_num_sources = ntohs(* (uint16_t *) (group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); - -    memcpy(&rec_group, group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, sizeof(struct in_addr)); - -    if (PIM_DEBUG_IGMP_PACKETS) { -      zlog_debug("Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", -                 from_str, ifp->name, i, rec_type, rec_auxdatalen, rec_num_sources, inet_ntoa(rec_group)); -    } - -    /* Scan sources */ - -    sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; - -    for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { - -      if ((src + 4) > report_pastend) { -        zlog_warn("Recv IGMP report v3 from %s on %s: group source beyond report end", -                  from_str, ifp->name); -        return -1; -      } - -      if (PIM_DEBUG_IGMP_PACKETS) { -        char src_str[200]; - -        if (!inet_ntop(AF_INET, src, src_str , sizeof(src_str))) -          sprintf(src_str, "<source?>"); - -        zlog_debug("Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", -                   from_str, ifp->name, i, inet_ntoa(rec_group), src_str); -      } -    } /* for (sources) */ - - -    lncb.family = AF_INET; -    lncb.u.prefix4.s_addr = 0x000000E0; -    lncb.prefixlen = 24; - -    g.family = AF_INET; -    g.u.prefix4 = rec_group; -    g.prefixlen = 32; -    /* -     * If we receive a igmp report with the group in 224.0.0.0/24 -     * then we should ignore it -     */ -    if (prefix_match(&lncb, &g)) -      local_ncb = 1; - -    if (!local_ncb) -      switch (rec_type) { -      case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: -        igmpv3_report_isin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); -        break; -      case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: -        igmpv3_report_isex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources, 0); -        break; -      case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: -        igmpv3_report_toin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); -        break; -      case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: -        igmpv3_report_toex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); -        break; -      case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: -        igmpv3_report_allow(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); -        break; -      case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: -        igmpv3_report_block(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); -        break; -      default: -        zlog_warn("Recv IGMP report v3 from %s on %s: unknown record type: type=%d", -                  from_str, ifp->name, rec_type); -      } - -    group_record += 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); -    local_ncb = 0; - -  } /* for (group records) */ - -  return 0; +	uint16_t recv_checksum; +	uint16_t checksum; +	int num_groups; +	uint8_t *group_record; +	uint8_t *report_pastend = (uint8_t *)igmp_msg + igmp_msg_len; +	struct interface *ifp = igmp->interface; +	int i; +	int local_ncb = 0; + +	if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { +		zlog_warn( +			"Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", +			from_str, ifp->name, igmp_msg_len, +			IGMP_V3_MSG_MIN_SIZE); +		return -1; +	} + +	recv_checksum = *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET); + +	/* for computing checksum */ +	*(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; + +	checksum = in_cksum(igmp_msg, igmp_msg_len); +	if (checksum != recv_checksum) { +		zlog_warn( +			"Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", +			from_str, ifp->name, recv_checksum, checksum); +		return -1; +	} + +	num_groups = ntohs( +		*(uint16_t *)(igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); +	if (num_groups < 1) { +		zlog_warn( +			"Recv IGMP report v3 from %s on %s: missing group records", +			from_str, ifp->name); +		return -1; +	} + +	if (PIM_DEBUG_IGMP_PACKETS) { +		zlog_debug( +			"Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", +			from_str, ifp->name, igmp_msg_len, checksum, +			num_groups); +	} + +	group_record = (uint8_t *)igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; + +	/* Scan groups */ +	for (i = 0; i < num_groups; ++i) { +		struct in_addr rec_group; +		uint8_t *sources; +		uint8_t *src; +		int rec_type; +		int rec_auxdatalen; +		int rec_num_sources; +		int j; +		struct prefix lncb; +		struct prefix g; + +		if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) +		    > report_pastend) { +			zlog_warn( +				"Recv IGMP report v3 from %s on %s: group record beyond report end", +				from_str, ifp->name); +			return -1; +		} + +		rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; +		rec_auxdatalen = +			group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; +		rec_num_sources = ntohs(*( +			uint16_t *)(group_record +				    + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); + +		memcpy(&rec_group, +		       group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, +		       sizeof(struct in_addr)); + +		if (PIM_DEBUG_IGMP_PACKETS) { +			zlog_debug( +				"Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", +				from_str, ifp->name, i, rec_type, +				rec_auxdatalen, rec_num_sources, +				inet_ntoa(rec_group)); +		} + +		/* Scan sources */ + +		sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; + +		for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { + +			if ((src + 4) > report_pastend) { +				zlog_warn( +					"Recv IGMP report v3 from %s on %s: group source beyond report end", +					from_str, ifp->name); +				return -1; +			} + +			if (PIM_DEBUG_IGMP_PACKETS) { +				char src_str[200]; + +				if (!inet_ntop(AF_INET, src, src_str, +					       sizeof(src_str))) +					sprintf(src_str, "<source?>"); + +				zlog_debug( +					"Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", +					from_str, ifp->name, i, +					inet_ntoa(rec_group), src_str); +			} +		} /* for (sources) */ + + +		lncb.family = AF_INET; +		lncb.u.prefix4.s_addr = 0x000000E0; +		lncb.prefixlen = 24; + +		g.family = AF_INET; +		g.u.prefix4 = rec_group; +		g.prefixlen = 32; +		/* +		 * If we receive a igmp report with the group in 224.0.0.0/24 +		 * then we should ignore it +		 */ +		if (prefix_match(&lncb, &g)) +			local_ncb = 1; + +		if (!local_ncb) +			switch (rec_type) { +			case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: +				igmpv3_report_isin(igmp, from, rec_group, +						   rec_num_sources, +						   (struct in_addr *)sources); +				break; +			case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: +				igmpv3_report_isex( +					igmp, from, rec_group, rec_num_sources, +					(struct in_addr *)sources, 0); +				break; +			case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: +				igmpv3_report_toin(igmp, from, rec_group, +						   rec_num_sources, +						   (struct in_addr *)sources); +				break; +			case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: +				igmpv3_report_toex(igmp, from, rec_group, +						   rec_num_sources, +						   (struct in_addr *)sources); +				break; +			case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: +				igmpv3_report_allow(igmp, from, rec_group, +						    rec_num_sources, +						    (struct in_addr *)sources); +				break; +			case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: +				igmpv3_report_block(igmp, from, rec_group, +						    rec_num_sources, +						    (struct in_addr *)sources); +				break; +			default: +				zlog_warn( +					"Recv IGMP report v3 from %s on %s: unknown record type: type=%d", +					from_str, ifp->name, rec_type); +			} + +		group_record += +			8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); +		local_ncb = 0; + +	} /* for (group records) */ + +	return 0;  } diff --git a/pimd/pim_igmpv3.h b/pimd/pim_igmpv3.h index 99f7b84b81..6abaef6e26 100644 --- a/pimd/pim_igmpv3.h +++ b/pimd/pim_igmpv3.h @@ -52,8 +52,7 @@  #define PIM_IGMP_OHPI_DSEC(qrv,qqi,qri_dsec) ((qrv) * (10 * (qqi)) + (qri_dsec))  void igmp_group_reset_gmi(struct igmp_group *group); -void igmp_source_reset_gmi(struct igmp_sock *igmp, -			   struct igmp_group *group, +void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group,  			   struct igmp_source *source);  void igmp_source_free(struct igmp_source *source); @@ -61,24 +60,23 @@ void igmp_source_delete(struct igmp_source *source);  void igmp_source_delete_expired(struct list *source_list);  void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -			int num_sources, struct in_addr *sources); +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources);  void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -                        int num_sources, struct in_addr *sources, -                        int from_igmp_v2_report); +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources, int from_igmp_v2_report);  void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -			int num_sources, struct in_addr *sources); +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources);  void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, -			struct in_addr group_addr, -			int num_sources, struct in_addr *sources); +			struct in_addr group_addr, int num_sources, +			struct in_addr *sources);  void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, -			 struct in_addr group_addr, -			 int num_sources, struct in_addr *sources); +			 struct in_addr group_addr, int num_sources, +			 struct in_addr *sources);  void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from, -			 struct in_addr group_addr, -			 int num_sources, struct in_addr *sources); +			 struct in_addr group_addr, int num_sources, +			 struct in_addr *sources);  void igmp_group_timer_lower_to_lmqt(struct igmp_group *group);  void igmp_source_timer_lower_to_lmqt(struct igmp_source *source); @@ -86,24 +84,17 @@ void igmp_source_timer_lower_to_lmqt(struct igmp_source *source);  struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group,  					     struct in_addr src_addr); -void igmp_v3_send_query (struct igmp_group *group, -                         int fd, -                         const char *ifname, -                         char *query_buf, -                         int query_buf_size, -                         int num_sources, -                         struct in_addr dst_addr, -                         struct in_addr group_addr, -                         int query_max_response_time_dsec, -                         uint8_t s_flag, -                         uint8_t querier_robustness_variable, -                         uint16_t querier_query_interval); - -void igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, -                         char *igmp_msg); - -int igmp_v3_recv_report (struct igmp_sock *igmp, -                         struct in_addr from, const char *from_str, -                         char *igmp_msg, int igmp_msg_len); +void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, +			char *query_buf, int query_buf_size, int num_sources, +			struct in_addr dst_addr, struct in_addr group_addr, +			int query_max_response_time_dsec, uint8_t s_flag, +			uint8_t querier_robustness_variable, +			uint16_t querier_query_interval); + +void igmp_v3_recv_query(struct igmp_sock *igmp, const char *from_str, +			char *igmp_msg); + +int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, +			const char *from_str, char *igmp_msg, int igmp_msg_len);  #endif /* PIM_IGMPV3_H */ diff --git a/pimd/pim_int.c b/pimd/pim_int.c index 577bf15c6a..3778399063 100644 --- a/pimd/pim_int.c +++ b/pimd/pim_int.c @@ -27,18 +27,18 @@  uint32_t pim_read_uint32_host(const uint8_t *buf)  { -  uint32_t val; -  memcpy(&val, buf, sizeof(val)); -  /* val is in netorder */ -  val = ntohl(val); -  /* val is in hostorder */ -  return val; +	uint32_t val; +	memcpy(&val, buf, sizeof(val)); +	/* val is in netorder */ +	val = ntohl(val); +	/* val is in hostorder */ +	return val;  }  void pim_write_uint32(uint8_t *buf, uint32_t val_host)  { -  /* val_host is in host order */ -  val_host = htonl(val_host); -  /* val_host is in netorder */ -  memcpy(buf, &val_host, sizeof(val_host)); +	/* val_host is in host order */ +	val_host = htonl(val_host); +	/* val_host is in netorder */ +	memcpy(buf, &val_host, sizeof(val_host));  } diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 35deecfd81..9bc5c2d9cc 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -39,301 +39,295 @@  #include "pim_rp.h"  #include "pim_jp_agg.h" -static void -on_trace (const char *label, -	  struct interface *ifp, struct in_addr src) +static void on_trace(const char *label, struct interface *ifp, +		     struct in_addr src)  { -  if (PIM_DEBUG_PIM_TRACE) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); -    zlog_debug("%s: from %s on %s", -	       label, src_str, ifp->name); -  } +	if (PIM_DEBUG_PIM_TRACE) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src, src_str, sizeof(src_str)); +		zlog_debug("%s: from %s on %s", label, src_str, ifp->name); +	}  } -static void recv_join(struct interface *ifp, -		      struct pim_neighbor *neigh, -		      uint16_t holdtime, -		      struct in_addr upstream, -		      struct prefix_sg *sg, -		      uint8_t source_flags) +static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, +		      uint16_t holdtime, struct in_addr upstream, +		      struct prefix_sg *sg, uint8_t source_flags)  { -  struct pim_interface *pim_ifp = NULL; - -  if (PIM_DEBUG_PIM_TRACE) { -    char up_str[INET_ADDRSTRLEN]; -    char neigh_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); -    pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); -    zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", -	      __PRETTY_FUNCTION__, -	      pim_str_sg_dump (sg), -	      source_flags & PIM_RPT_BIT_MASK, -	      source_flags & PIM_WILDCARD_BIT_MASK, -	      up_str, holdtime, neigh_str, ifp->name); -  } - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  ++pim_ifp->pim_ifstat_join_recv; - -  /* -   * If the RPT and WC are set it's a (*,G) -   * and the source is the RP -   */ -  if ((source_flags & PIM_RPT_BIT_MASK) && -      (source_flags & PIM_WILDCARD_BIT_MASK)) -    { -      struct pim_rpf *rp = RP (sg->grp); - -      /* -       * If the RP sent in the message is not -       * our RP for the group, drop the message -       */ -      if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) -	return; - -      sg->src.s_addr = INADDR_ANY; -    } - -  /* Restart join expiry timer */ -  pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, -			 sg, source_flags, holdtime); - +	struct pim_interface *pim_ifp = NULL; + +	if (PIM_DEBUG_PIM_TRACE) { +		char up_str[INET_ADDRSTRLEN]; +		char neigh_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); +		pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, +			       sizeof(neigh_str)); +		zlog_warn( +			"%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", +			__PRETTY_FUNCTION__, pim_str_sg_dump(sg), +			source_flags & PIM_RPT_BIT_MASK, +			source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, +			neigh_str, ifp->name); +	} + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	++pim_ifp->pim_ifstat_join_recv; + +	/* +	 * If the RPT and WC are set it's a (*,G) +	 * and the source is the RP +	 */ +	if ((source_flags & PIM_RPT_BIT_MASK) +	    && (source_flags & PIM_WILDCARD_BIT_MASK)) { +		struct pim_rpf *rp = RP(sg->grp); + +		/* +		 * If the RP sent in the message is not +		 * our RP for the group, drop the message +		 */ +		if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) +			return; + +		sg->src.s_addr = INADDR_ANY; +	} + +	/* Restart join expiry timer */ +	pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, sg, +			       source_flags, holdtime);  } -static void recv_prune(struct interface *ifp, -		       struct pim_neighbor *neigh, -		       uint16_t holdtime, -		       struct in_addr upstream, -		       struct prefix_sg *sg, -		       uint8_t source_flags) +static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, +		       uint16_t holdtime, struct in_addr upstream, +		       struct prefix_sg *sg, uint8_t source_flags)  { -  struct pim_interface *pim_ifp = NULL; - -  if (PIM_DEBUG_PIM_TRACE) { -    char up_str[INET_ADDRSTRLEN]; -    char neigh_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); -    pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); -    zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", -	      __PRETTY_FUNCTION__, -	      pim_str_sg_dump (sg), -	      source_flags & PIM_RPT_BIT_MASK, -	      source_flags & PIM_WILDCARD_BIT_MASK, -	      up_str, holdtime, neigh_str, ifp->name); -  } - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  ++pim_ifp->pim_ifstat_prune_recv; - -  if ((source_flags & PIM_RPT_BIT_MASK) && -      (source_flags & PIM_WILDCARD_BIT_MASK)) -    { -      struct pim_rpf *rp = RP (sg->grp); - -      // Ignoring Prune *,G's at the moment. -      if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) -	return; - -      sg->src.s_addr = INADDR_ANY; -    } - -  pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime); - +	struct pim_interface *pim_ifp = NULL; + +	if (PIM_DEBUG_PIM_TRACE) { +		char up_str[INET_ADDRSTRLEN]; +		char neigh_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); +		pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, +			       sizeof(neigh_str)); +		zlog_warn( +			"%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", +			__PRETTY_FUNCTION__, pim_str_sg_dump(sg), +			source_flags & PIM_RPT_BIT_MASK, +			source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, +			neigh_str, ifp->name); +	} + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	++pim_ifp->pim_ifstat_prune_recv; + +	if ((source_flags & PIM_RPT_BIT_MASK) +	    && (source_flags & PIM_WILDCARD_BIT_MASK)) { +		struct pim_rpf *rp = RP(sg->grp); + +		// Ignoring Prune *,G's at the moment. +		if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) +			return; + +		sg->src.s_addr = INADDR_ANY; +	} + +	pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime);  } -int pim_joinprune_recv(struct interface *ifp, -		       struct pim_neighbor *neigh, -		       struct in_addr src_addr, -		       uint8_t *tlv_buf, int tlv_buf_size) +int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, +		       struct in_addr src_addr, uint8_t *tlv_buf, +		       int tlv_buf_size)  { -  struct prefix   msg_upstream_addr; -  uint8_t         msg_num_groups; -  uint16_t        msg_holdtime; -  int             addr_offset; -  uint8_t        *buf; -  uint8_t        *pastend; -  int             remain; -  int             group; - -  buf     = tlv_buf; -  pastend = tlv_buf + tlv_buf_size; - -  /* -    Parse ucast addr -  */ -  addr_offset = pim_parse_addr_ucast (&msg_upstream_addr, -				      buf, pastend - buf); -  if (addr_offset < 1) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", -	      __PRETTY_FUNCTION__, -	      src_str, ifp->name); -    return -1; -  } -  buf += addr_offset; - -  /* -    Check upstream address family -   */ -  if (msg_upstream_addr.family != AF_INET) { -    if (PIM_DEBUG_PIM_J_P) { -      char src_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -      zlog_warn("%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s", -		__PRETTY_FUNCTION__, -		msg_upstream_addr.family, src_str, ifp->name); -    } -    return -2; -  } - -  remain = pastend - buf; -  if (remain < 4) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s", -	      __PRETTY_FUNCTION__, -	      remain, 4, src_str, ifp->name); -    return -4; -  } - -  ++buf; /* skip reserved byte */ -  msg_num_groups = *(const uint8_t *) buf; -  ++buf; -  msg_holdtime = ntohs(*(const uint16_t *) buf); -  ++buf; -  ++buf; - -  if (PIM_DEBUG_PIM_J_P) { -    char src_str[INET_ADDRSTRLEN]; -    char upstream_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4, -		   upstream_str, sizeof(upstream_str)); -    zlog_debug ("%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", -		__PRETTY_FUNCTION__, -		upstream_str, msg_num_groups, msg_holdtime, -		src_str, ifp->name); -  } - -  /* Scan groups */ -  for (group = 0; group < msg_num_groups; ++group) { -    struct prefix_sg sg; -    uint8_t       msg_source_flags; -    uint16_t      msg_num_joined_sources; -    uint16_t      msg_num_pruned_sources; -    int           source; -    struct        pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; -    uint8_t       starg_alone = 0; - -    memset (&sg, 0, sizeof (struct prefix_sg)); -    addr_offset = pim_parse_addr_group (&sg, -					buf, pastend - buf); -    if (addr_offset < 1) { -      return -5; -    } -    buf += addr_offset; - -    remain = pastend - buf; -    if (remain < 4) { -      char src_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -      zlog_warn("%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s", -		__PRETTY_FUNCTION__, -		remain, 4, src_str, ifp->name); -      return -6; -    } - -    msg_num_joined_sources = ntohs(*(const uint16_t *) buf); -    buf += 2; -    msg_num_pruned_sources = ntohs(*(const uint16_t *) buf); -    buf += 2; - -    if (PIM_DEBUG_PIM_J_P) { -      char src_str[INET_ADDRSTRLEN]; -      char upstream_str[INET_ADDRSTRLEN]; -      char group_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -      pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4, -		     upstream_str, sizeof(upstream_str)); -      pim_inet4_dump("<grp?>", sg.grp, -		     group_str, sizeof(group_str)); -      zlog_warn("%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s", -		__PRETTY_FUNCTION__, -		upstream_str, group_str, -		msg_num_joined_sources, msg_num_pruned_sources, -		src_str, ifp->name); -    } - -    /* Scan joined sources */ -    for (source = 0; source < msg_num_joined_sources; ++source) { -      addr_offset = pim_parse_addr_source (&sg, -					   &msg_source_flags, -					   buf, pastend - buf); -      if (addr_offset < 1) { -	return -7; -      } - -      buf += addr_offset; - -      recv_join(ifp, neigh, msg_holdtime, -		msg_upstream_addr.u.prefix4, -		&sg, -		msg_source_flags); - -      if (sg.src.s_addr == INADDR_ANY) -        { -          starg_alone = 1; -          starg_ch = pim_ifchannel_find (ifp, &sg); -	  if (starg_ch) -	    pim_ifchannel_set_star_g_join_state (starg_ch, 0, msg_source_flags, 1, starg_alone); -        } -    } - -    /* Scan pruned sources */ -    for (source = 0; source < msg_num_pruned_sources; ++source) { -      addr_offset = pim_parse_addr_source (&sg, -					   &msg_source_flags, -					   buf, pastend - buf); -      if (addr_offset < 1) { -	return -8; -      } - -      sg_ch = pim_ifchannel_find (ifp, &sg); - -      buf += addr_offset; -      starg_alone = 0; -      recv_prune(ifp, neigh, msg_holdtime, -		 msg_upstream_addr.u.prefix4, -		 &sg, -		 msg_source_flags); - -      /* Received SG-RPT Prune delete oif from specific S,G */ -      if (starg_ch && sg_ch && (msg_source_flags & PIM_RPT_BIT_MASK) -               && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) -        { -          struct pim_upstream *up = sg_ch->upstream; -          PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags); -          if (up) -            { -              if (PIM_DEBUG_TRACE) -                zlog_debug ("%s: SGRpt flag is set, del inherit oif from up %s", -                     __PRETTY_FUNCTION__, up->sg_str); -              pim_channel_del_oif (up->channel_oil, starg_ch->interface, PIM_OIF_FLAG_PROTO_STAR); -            } -        } -    } -    if (starg_ch) -      pim_ifchannel_set_star_g_join_state (starg_ch, 1, msg_source_flags, 0, starg_alone); -    starg_ch = NULL; -  } /* scan groups */ - -  return 0; +	struct prefix msg_upstream_addr; +	uint8_t msg_num_groups; +	uint16_t msg_holdtime; +	int addr_offset; +	uint8_t *buf; +	uint8_t *pastend; +	int remain; +	int group; + +	buf = tlv_buf; +	pastend = tlv_buf + tlv_buf_size; + +	/* +	  Parse ucast addr +	*/ +	addr_offset = +		pim_parse_addr_ucast(&msg_upstream_addr, buf, pastend - buf); +	if (addr_offset < 1) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", +			  __PRETTY_FUNCTION__, src_str, ifp->name); +		return -1; +	} +	buf += addr_offset; + +	/* +	  Check upstream address family +	 */ +	if (msg_upstream_addr.family != AF_INET) { +		if (PIM_DEBUG_PIM_J_P) { +			char src_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<src?>", src_addr, src_str, +				       sizeof(src_str)); +			zlog_warn( +				"%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s", +				__PRETTY_FUNCTION__, msg_upstream_addr.family, +				src_str, ifp->name); +		} +		return -2; +	} + +	remain = pastend - buf; +	if (remain < 4) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn( +			"%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s", +			__PRETTY_FUNCTION__, remain, 4, src_str, ifp->name); +		return -4; +	} + +	++buf; /* skip reserved byte */ +	msg_num_groups = *(const uint8_t *)buf; +	++buf; +	msg_holdtime = ntohs(*(const uint16_t *)buf); +	++buf; +	++buf; + +	if (PIM_DEBUG_PIM_J_P) { +		char src_str[INET_ADDRSTRLEN]; +		char upstream_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4, +			       upstream_str, sizeof(upstream_str)); +		zlog_debug( +			"%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", +			__PRETTY_FUNCTION__, upstream_str, msg_num_groups, +			msg_holdtime, src_str, ifp->name); +	} + +	/* Scan groups */ +	for (group = 0; group < msg_num_groups; ++group) { +		struct prefix_sg sg; +		uint8_t msg_source_flags; +		uint16_t msg_num_joined_sources; +		uint16_t msg_num_pruned_sources; +		int source; +		struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; +		uint8_t starg_alone = 0; + +		memset(&sg, 0, sizeof(struct prefix_sg)); +		addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf); +		if (addr_offset < 1) { +			return -5; +		} +		buf += addr_offset; + +		remain = pastend - buf; +		if (remain < 4) { +			char src_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<src?>", src_addr, src_str, +				       sizeof(src_str)); +			zlog_warn( +				"%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s", +				__PRETTY_FUNCTION__, remain, 4, src_str, +				ifp->name); +			return -6; +		} + +		msg_num_joined_sources = ntohs(*(const uint16_t *)buf); +		buf += 2; +		msg_num_pruned_sources = ntohs(*(const uint16_t *)buf); +		buf += 2; + +		if (PIM_DEBUG_PIM_J_P) { +			char src_str[INET_ADDRSTRLEN]; +			char upstream_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<src?>", src_addr, src_str, +				       sizeof(src_str)); +			pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4, +				       upstream_str, sizeof(upstream_str)); +			pim_inet4_dump("<grp?>", sg.grp, group_str, +				       sizeof(group_str)); +			zlog_warn( +				"%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s", +				__PRETTY_FUNCTION__, upstream_str, group_str, +				msg_num_joined_sources, msg_num_pruned_sources, +				src_str, ifp->name); +		} + +		/* Scan joined sources */ +		for (source = 0; source < msg_num_joined_sources; ++source) { +			addr_offset = pim_parse_addr_source( +				&sg, &msg_source_flags, buf, pastend - buf); +			if (addr_offset < 1) { +				return -7; +			} + +			buf += addr_offset; + +			recv_join(ifp, neigh, msg_holdtime, +				  msg_upstream_addr.u.prefix4, &sg, +				  msg_source_flags); + +			if (sg.src.s_addr == INADDR_ANY) { +				starg_alone = 1; +				starg_ch = pim_ifchannel_find(ifp, &sg); +				if (starg_ch) +					pim_ifchannel_set_star_g_join_state( +						starg_ch, 0, msg_source_flags, +						1, starg_alone); +			} +		} + +		/* Scan pruned sources */ +		for (source = 0; source < msg_num_pruned_sources; ++source) { +			addr_offset = pim_parse_addr_source( +				&sg, &msg_source_flags, buf, pastend - buf); +			if (addr_offset < 1) { +				return -8; +			} + +			sg_ch = pim_ifchannel_find(ifp, &sg); + +			buf += addr_offset; +			starg_alone = 0; +			recv_prune(ifp, neigh, msg_holdtime, +				   msg_upstream_addr.u.prefix4, &sg, +				   msg_source_flags); + +			/* Received SG-RPT Prune delete oif from specific S,G */ +			if (starg_ch && sg_ch +			    && (msg_source_flags & PIM_RPT_BIT_MASK) +			    && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) { +				struct pim_upstream *up = sg_ch->upstream; +				PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags); +				if (up) { +					if (PIM_DEBUG_TRACE) +						zlog_debug( +							"%s: SGRpt flag is set, del inherit oif from up %s", +							__PRETTY_FUNCTION__, +							up->sg_str); +					pim_channel_del_oif( +						up->channel_oil, +						starg_ch->interface, +						PIM_OIF_FLAG_PROTO_STAR); +				} +			} +		} +		if (starg_ch) +			pim_ifchannel_set_star_g_join_state( +				starg_ch, 1, msg_source_flags, 0, starg_alone); +		starg_ch = NULL; +	} /* scan groups */ + +	return 0;  }  /* @@ -402,177 +396,187 @@ int pim_joinprune_recv(struct interface *ifp,   *  |        Pruned Source Address n (Encoded-Source format)        |   *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   */ -int pim_joinprune_send(struct pim_rpf *rpf, -                       struct list *groups) +int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)  { -  struct pim_jp_agg_group *group; -  struct pim_interface *pim_ifp = NULL; -  struct pim_jp_groups *grp = NULL; -  struct pim_jp *msg; -  struct listnode *node, *nnode; -  uint8_t pim_msg[10000]; -  uint8_t *curr_ptr = pim_msg; -  bool new_packet = true; -  size_t packet_left = 0; -  size_t packet_size = 0; -  size_t group_size = 0; - -  on_trace (__PRETTY_FUNCTION__, rpf->source_nexthop.interface, rpf->rpf_addr.u.prefix4); - -  if (rpf->source_nexthop.interface) -    pim_ifp = rpf->source_nexthop.interface->info; -  else -    { -      zlog_warn ("%s: RPF interface is not present", __PRETTY_FUNCTION__); -      return -1; -    } - -  if (!pim_ifp) -    { -      zlog_warn ("%s: multicast not enabled on interface %s", -              __PRETTY_FUNCTION__, -              rpf->source_nexthop.interface->name); -      return -1; -    } - -  if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) -    { -      if (PIM_DEBUG_PIM_J_P) { -        char dst_str[INET_ADDRSTRLEN]; -        pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); -        zlog_debug("%s: upstream=%s is myself on interface %s", -                   __PRETTY_FUNCTION__, -                   dst_str, rpf->source_nexthop.interface->name); -      } -      return 0; -    } - -  /* -    RFC 4601: 4.3.1.  Sending Hello Messages - -    Thus, if a router needs to send a Join/Prune or Assert message on -    an interface on which it has not yet sent a Hello message with the -    currently configured IP address, then it MUST immediately send the -    relevant Hello message without waiting for the Hello Timer to -    expire, followed by the Join/Prune or Assert message. -  */ -  pim_hello_require(rpf->source_nexthop.interface); - -  for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) -    { -      if (new_packet) -        { -          msg = (struct pim_jp *)pim_msg; - -          memset(msg, 0, sizeof (*msg)); - -          pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); -          msg->reserved   = 0; -          msg->holdtime   = htons(PIM_JP_HOLDTIME); - -          new_packet = false; - -          grp = &msg->groups[0]; -          curr_ptr = (uint8_t *)grp; -          packet_size  = sizeof (struct pim_msg_header); -          packet_size += sizeof (struct pim_encoded_ipv4_unicast); -          packet_size += 4;  // reserved (1) + groups (1) + holdtime (2) - -          packet_left = rpf->source_nexthop.interface->mtu - 24; -          packet_left -= packet_size; -        } -      if (PIM_DEBUG_PIM_J_P) { -        char dst_str[INET_ADDRSTRLEN]; -        char grp_str[INET_ADDRSTRLEN]; -        pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); -        pim_inet4_dump("<grp?>", group->group, grp_str, sizeof(grp_str)); -        zlog_debug("%s: sending (G)=%s to upstream=%s on interface %s", -                   __PRETTY_FUNCTION__, -                   grp_str, dst_str, rpf->source_nexthop.interface->name); -      } - -      group_size = pim_msg_get_jp_group_size (group->sources); -      if (group_size > packet_left) -        { -          pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); -          if (pim_msg_send(pim_ifp->pim_sock_fd, -                           pim_ifp->primary_address, -                           qpim_all_pim_routers_addr, -                           pim_msg, -                           packet_size, -                           rpf->source_nexthop.interface->name)) { -            zlog_warn("%s: could not send PIM message on interface %s", -                      __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); -          } - -          msg = (struct pim_jp *)pim_msg; -          memset(msg, 0, sizeof (*msg)); - -          pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); -          msg->reserved   = 0; -          msg->holdtime   = htons(PIM_JP_HOLDTIME); - -          new_packet = false; - -          grp = &msg->groups[0]; -          curr_ptr = (uint8_t *)grp; -          packet_size  = sizeof (struct pim_msg_header); -          packet_size += sizeof (struct pim_encoded_ipv4_unicast); -          packet_size += 4;  // reserved (1) + groups (1) + holdtime (2) - -          packet_left = rpf->source_nexthop.interface->mtu - 24; -          packet_left -= packet_size; -        } - -      msg->num_groups++; -      /* -        Build PIM message -      */ - -      curr_ptr += group_size; -      packet_left -= group_size; -      packet_size += group_size; -      pim_msg_build_jp_groups (grp, group, group_size); - -      pim_ifp->pim_ifstat_join_send += ntohs(grp->joins); -      pim_ifp->pim_ifstat_prune_send += ntohs(grp->prunes); - -      if (PIM_DEBUG_PIM_TRACE) -        zlog_debug ("%s: interface %s num_joins %u num_prunes %u", __PRETTY_FUNCTION__, -          rpf->source_nexthop.interface->name, ntohs(grp->joins), ntohs (grp->prunes)); - -      grp = (struct pim_jp_groups *)curr_ptr; -      if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255) -        { -          pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); -          if (pim_msg_send(pim_ifp->pim_sock_fd, -                           pim_ifp->primary_address, -                           qpim_all_pim_routers_addr, -                           pim_msg, -                           packet_size, -                           rpf->source_nexthop.interface->name)) { -            zlog_warn("%s: could not send PIM message on interface %s", -                      __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); -          } - -          new_packet = true; -        } -    } - - -  if (!new_packet) -    { -      //msg->num_groups = htons (msg->num_groups); -      pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); -      if (pim_msg_send(pim_ifp->pim_sock_fd, -                       pim_ifp->primary_address, -                       qpim_all_pim_routers_addr, -                       pim_msg, -                       packet_size, -                       rpf->source_nexthop.interface->name)) { -        zlog_warn("%s: could not send PIM message on interface %s", -                  __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); -      } -    } -  return 0; +	struct pim_jp_agg_group *group; +	struct pim_interface *pim_ifp = NULL; +	struct pim_jp_groups *grp = NULL; +	struct pim_jp *msg; +	struct listnode *node, *nnode; +	uint8_t pim_msg[10000]; +	uint8_t *curr_ptr = pim_msg; +	bool new_packet = true; +	size_t packet_left = 0; +	size_t packet_size = 0; +	size_t group_size = 0; + +	on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface, +		 rpf->rpf_addr.u.prefix4); + +	if (rpf->source_nexthop.interface) +		pim_ifp = rpf->source_nexthop.interface->info; +	else { +		zlog_warn("%s: RPF interface is not present", +			  __PRETTY_FUNCTION__); +		return -1; +	} + +	if (!pim_ifp) { +		zlog_warn("%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, +			  rpf->source_nexthop.interface->name); +		return -1; +	} + +	if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) { +		if (PIM_DEBUG_PIM_J_P) { +			char dst_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, +				       dst_str, sizeof(dst_str)); +			zlog_debug("%s: upstream=%s is myself on interface %s", +				   __PRETTY_FUNCTION__, dst_str, +				   rpf->source_nexthop.interface->name); +		} +		return 0; +	} + +	/* +	  RFC 4601: 4.3.1.  Sending Hello Messages + +	  Thus, if a router needs to send a Join/Prune or Assert message on +	  an interface on which it has not yet sent a Hello message with the +	  currently configured IP address, then it MUST immediately send the +	  relevant Hello message without waiting for the Hello Timer to +	  expire, followed by the Join/Prune or Assert message. +	*/ +	pim_hello_require(rpf->source_nexthop.interface); + +	for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) { +		if (new_packet) { +			msg = (struct pim_jp *)pim_msg; + +			memset(msg, 0, sizeof(*msg)); + +			pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr, +						       rpf->rpf_addr.u.prefix4); +			msg->reserved = 0; +			msg->holdtime = htons(PIM_JP_HOLDTIME); + +			new_packet = false; + +			grp = &msg->groups[0]; +			curr_ptr = (uint8_t *)grp; +			packet_size = sizeof(struct pim_msg_header); +			packet_size += sizeof(struct pim_encoded_ipv4_unicast); +			packet_size += +				4; // reserved (1) + groups (1) + holdtime (2) + +			packet_left = rpf->source_nexthop.interface->mtu - 24; +			packet_left -= packet_size; +		} +		if (PIM_DEBUG_PIM_J_P) { +			char dst_str[INET_ADDRSTRLEN]; +			char grp_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, +				       dst_str, sizeof(dst_str)); +			pim_inet4_dump("<grp?>", group->group, grp_str, +				       sizeof(grp_str)); +			zlog_debug( +				"%s: sending (G)=%s to upstream=%s on interface %s", +				__PRETTY_FUNCTION__, grp_str, dst_str, +				rpf->source_nexthop.interface->name); +		} + +		group_size = pim_msg_get_jp_group_size(group->sources); +		if (group_size > packet_left) { +			pim_msg_build_header(pim_msg, packet_size, +					     PIM_MSG_TYPE_JOIN_PRUNE); +			if (pim_msg_send(pim_ifp->pim_sock_fd, +					 pim_ifp->primary_address, +					 qpim_all_pim_routers_addr, pim_msg, +					 packet_size, +					 rpf->source_nexthop.interface->name)) { +				zlog_warn( +					"%s: could not send PIM message on interface %s", +					__PRETTY_FUNCTION__, +					rpf->source_nexthop.interface->name); +			} + +			msg = (struct pim_jp *)pim_msg; +			memset(msg, 0, sizeof(*msg)); + +			pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr, +						       rpf->rpf_addr.u.prefix4); +			msg->reserved = 0; +			msg->holdtime = htons(PIM_JP_HOLDTIME); + +			new_packet = false; + +			grp = &msg->groups[0]; +			curr_ptr = (uint8_t *)grp; +			packet_size = sizeof(struct pim_msg_header); +			packet_size += sizeof(struct pim_encoded_ipv4_unicast); +			packet_size += +				4; // reserved (1) + groups (1) + holdtime (2) + +			packet_left = rpf->source_nexthop.interface->mtu - 24; +			packet_left -= packet_size; +		} + +		msg->num_groups++; +		/* +		  Build PIM message +		*/ + +		curr_ptr += group_size; +		packet_left -= group_size; +		packet_size += group_size; +		pim_msg_build_jp_groups(grp, group, group_size); + +		pim_ifp->pim_ifstat_join_send += ntohs(grp->joins); +		pim_ifp->pim_ifstat_prune_send += ntohs(grp->prunes); + +		if (PIM_DEBUG_PIM_TRACE) +			zlog_debug( +				"%s: interface %s num_joins %u num_prunes %u", +				__PRETTY_FUNCTION__, +				rpf->source_nexthop.interface->name, +				ntohs(grp->joins), ntohs(grp->prunes)); + +		grp = (struct pim_jp_groups *)curr_ptr; +		if (packet_left < sizeof(struct pim_jp_groups) +		    || msg->num_groups == 255) { +			pim_msg_build_header(pim_msg, packet_size, +					     PIM_MSG_TYPE_JOIN_PRUNE); +			if (pim_msg_send(pim_ifp->pim_sock_fd, +					 pim_ifp->primary_address, +					 qpim_all_pim_routers_addr, pim_msg, +					 packet_size, +					 rpf->source_nexthop.interface->name)) { +				zlog_warn( +					"%s: could not send PIM message on interface %s", +					__PRETTY_FUNCTION__, +					rpf->source_nexthop.interface->name); +			} + +			new_packet = true; +		} +	} + + +	if (!new_packet) { +		// msg->num_groups = htons (msg->num_groups); +		pim_msg_build_header(pim_msg, packet_size, +				     PIM_MSG_TYPE_JOIN_PRUNE); +		if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, +				 qpim_all_pim_routers_addr, pim_msg, +				 packet_size, +				 rpf->source_nexthop.interface->name)) { +			zlog_warn( +				"%s: could not send PIM message on interface %s", +				__PRETTY_FUNCTION__, +				rpf->source_nexthop.interface->name); +		} +	} +	return 0;  } diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 6dc1b3e8f1..5d28f2ba3c 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -26,12 +26,10 @@  #include "pim_neighbor.h" -int pim_joinprune_recv(struct interface *ifp, -		       struct pim_neighbor *neigh, -		       struct in_addr src_addr, -		       uint8_t *tlv_buf, int tlv_buf_size); +int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, +		       struct in_addr src_addr, uint8_t *tlv_buf, +		       int tlv_buf_size); -int pim_joinprune_send(struct pim_rpf *nexthop, -                       struct list *groups); +int pim_joinprune_send(struct pim_rpf *nexthop, struct list *groups);  #endif /* PIM_JOIN_H */ diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index 25530f40b9..16d55d7bf7 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -30,65 +30,63 @@  #include "pim_join.h"  #include "pim_iface.h" -void -pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag) +void pim_jp_agg_group_list_free(struct pim_jp_agg_group *jag)  { -  list_delete(jag->sources); +	list_delete(jag->sources); -  XFREE (MTYPE_PIM_JP_AGG_GROUP, jag); +	XFREE(MTYPE_PIM_JP_AGG_GROUP, jag);  } -static void -pim_jp_agg_src_free (struct pim_jp_sources *js) +static void pim_jp_agg_src_free(struct pim_jp_sources *js)  { -  struct pim_upstream *up = js->up; - -  /* -   * When we are being called here, we know -   * that the neighbor is going away start -   * the normal j/p timer so that it can -   * pick this shit back up when the -   * nbr comes back alive -   */ -  if (up) -    join_timer_start(js->up); -  XFREE (MTYPE_PIM_JP_AGG_SOURCE, js); +	struct pim_upstream *up = js->up; + +	/* +	 * When we are being called here, we know +	 * that the neighbor is going away start +	 * the normal j/p timer so that it can +	 * pick this shit back up when the +	 * nbr comes back alive +	 */ +	if (up) +		join_timer_start(js->up); +	XFREE(MTYPE_PIM_JP_AGG_SOURCE, js);  } -int -pim_jp_agg_group_list_cmp (void *arg1, void *arg2) +int pim_jp_agg_group_list_cmp(void *arg1, void *arg2)  { -  const struct pim_jp_agg_group *jag1 = (const struct pim_jp_agg_group *)arg1; -  const struct pim_jp_agg_group *jag2 = (const struct pim_jp_agg_group *)arg2; +	const struct pim_jp_agg_group *jag1 = +		(const struct pim_jp_agg_group *)arg1; +	const struct pim_jp_agg_group *jag2 = +		(const struct pim_jp_agg_group *)arg2; -  if (jag1->group.s_addr < jag2->group.s_addr) -    return -1; +	if (jag1->group.s_addr < jag2->group.s_addr) +		return -1; -  if (jag1->group.s_addr > jag2->group.s_addr) -    return 1; +	if (jag1->group.s_addr > jag2->group.s_addr) +		return 1; -  return 0; +	return 0;  } -static int -pim_jp_agg_src_cmp (void *arg1, void *arg2) +static int pim_jp_agg_src_cmp(void *arg1, void *arg2)  { -  const struct pim_jp_sources *js1 = (const struct pim_jp_sources *)arg1; -  const struct pim_jp_sources *js2 = (const struct pim_jp_sources *)arg2; +	const struct pim_jp_sources *js1 = (const struct pim_jp_sources *)arg1; +	const struct pim_jp_sources *js2 = (const struct pim_jp_sources *)arg2; -  if (js1->is_join && !js2->is_join) -    return -1; +	if (js1->is_join && !js2->is_join) +		return -1; -  if (!js1->is_join && js2->is_join) -    return 1; +	if (!js1->is_join && js2->is_join) +		return 1; -  if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) -    return -1; +	if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) +		return -1; -  if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) -    return 1; +	if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) +		return 1; -  return 0; +	return 0;  }  /* @@ -97,119 +95,107 @@ pim_jp_agg_src_cmp (void *arg1, void *arg2)   * figuring out where to send prunes   * and joins.   */ -void -pim_jp_agg_clear_group (struct list *group) +void pim_jp_agg_clear_group(struct list *group)  { -  struct listnode *gnode, *gnnode; -  struct listnode *snode, *snnode; -  struct pim_jp_agg_group *jag; -  struct pim_jp_sources *js; - -  for (ALL_LIST_ELEMENTS(group, gnode, gnnode, jag)) -    { -      for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) -        { -          listnode_delete(jag->sources, js); -          js->up = NULL; -          XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); -        } -      jag->sources = NULL; -      listnode_delete(group, jag); -      XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); -    } +	struct listnode *gnode, *gnnode; +	struct listnode *snode, *snnode; +	struct pim_jp_agg_group *jag; +	struct pim_jp_sources *js; + +	for (ALL_LIST_ELEMENTS(group, gnode, gnnode, jag)) { +		for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) { +			listnode_delete(jag->sources, js); +			js->up = NULL; +			XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); +		} +		jag->sources = NULL; +		listnode_delete(group, jag); +		XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); +	}  }  static struct pim_iface_upstream_switch * -pim_jp_agg_get_interface_upstream_switch_list (struct pim_rpf *rpf) +pim_jp_agg_get_interface_upstream_switch_list(struct pim_rpf *rpf)  { -  struct pim_interface *pim_ifp = rpf->source_nexthop.interface->info; -  struct pim_iface_upstream_switch *pius; -  struct listnode *node, *nnode; - -  /* Old interface is pim disabled */ -  if (!pim_ifp) -    return NULL; - -  for (ALL_LIST_ELEMENTS(pim_ifp->upstream_switch_list, node, nnode, pius)) -    { -      if (pius->address.s_addr == rpf->rpf_addr.u.prefix4.s_addr) -        break; -    } - -  if (!pius) -    { -      pius = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof (struct pim_iface_upstream_switch)); -      pius->address.s_addr = rpf->rpf_addr.u.prefix4.s_addr; -      pius->us = list_new(); -      listnode_add_sort (pim_ifp->upstream_switch_list, pius); -    } - -  return pius; +	struct pim_interface *pim_ifp = rpf->source_nexthop.interface->info; +	struct pim_iface_upstream_switch *pius; +	struct listnode *node, *nnode; + +	/* Old interface is pim disabled */ +	if (!pim_ifp) +		return NULL; + +	for (ALL_LIST_ELEMENTS(pim_ifp->upstream_switch_list, node, nnode, +			       pius)) { +		if (pius->address.s_addr == rpf->rpf_addr.u.prefix4.s_addr) +			break; +	} + +	if (!pius) { +		pius = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, +			       sizeof(struct pim_iface_upstream_switch)); +		pius->address.s_addr = rpf->rpf_addr.u.prefix4.s_addr; +		pius->us = list_new(); +		listnode_add_sort(pim_ifp->upstream_switch_list, pius); +	} + +	return pius;  } -void -pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up) +void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up)  { -  struct listnode *node, *nnode; -  struct pim_jp_agg_group *jag = NULL; -  struct pim_jp_sources *js = NULL; - -  for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) -    { -      if (jag->group.s_addr == up->sg.grp.s_addr) -        break; -    } - -  if (!jag) -    return; - -  for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) -    { -      if (js->up == up) -        break; -    } - -  if (js) -    { -      js->up = NULL; -      listnode_delete(jag->sources, js); -      XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); -    } - -  if (jag->sources->count == 0) -    { -      list_delete(jag->sources); -      jag->sources = NULL; -      listnode_delete(group, jag); -      XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); -    } - +	struct listnode *node, *nnode; +	struct pim_jp_agg_group *jag = NULL; +	struct pim_jp_sources *js = NULL; + +	for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { +		if (jag->group.s_addr == up->sg.grp.s_addr) +			break; +	} + +	if (!jag) +		return; + +	for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { +		if (js->up == up) +			break; +	} + +	if (js) { +		js->up = NULL; +		listnode_delete(jag->sources, js); +		XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); +	} + +	if (jag->sources->count == 0) { +		list_delete(jag->sources); +		jag->sources = NULL; +		listnode_delete(group, jag); +		XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); +	}  } -int -pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up) +int pim_jp_agg_is_in_list(struct list *group, struct pim_upstream *up)  { -  struct listnode *node, *nnode; -  struct pim_jp_agg_group *jag = NULL; -  struct pim_jp_sources *js = NULL; +	struct listnode *node, *nnode; +	struct pim_jp_agg_group *jag = NULL; +	struct pim_jp_sources *js = NULL; -  for (ALL_LIST_ELEMENTS (group, node, nnode, jag)) -    { -      if (jag->group.s_addr == up->sg.grp.s_addr) -        break; -    } +	for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { +		if (jag->group.s_addr == up->sg.grp.s_addr) +			break; +	} -  if (!jag) -    return 0; +	if (!jag) +		return 0; -  for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) -    { -      if (js->up == up) -        return 1; -    } +	for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { +		if (js->up == up) +			return 1; +	} -  return 0; - } +	return 0; +}  //#define PIM_JP_AGG_DEBUG 1  /* @@ -224,148 +210,137 @@ pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up)   * can be safely compiled out in real   * builds   */ -void -pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore) +void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore)  {  #ifdef PIM_JP_AGG_DEBUG -  struct listnode *node; -  struct interface *ifp; - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) -    { -      struct pim_interface *pim_ifp = ifp->info; -      struct listnode *nnode; - -      if (ignore && ifp == up->rpf.source_nexthop.interface) -        continue; - -      if (pim_ifp) -        { -          struct pim_neighbor *neigh; -          for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, nnode, neigh)) -            { -              assert (!pim_jp_agg_is_in_list(neigh->upstream_jp_agg, up)); -            } -        } -    } +	struct listnode *node; +	struct interface *ifp; + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		struct pim_interface *pim_ifp = ifp->info; +		struct listnode *nnode; + +		if (ignore && ifp == up->rpf.source_nexthop.interface) +			continue; + +		if (pim_ifp) { +			struct pim_neighbor *neigh; +			for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, +						  nnode, neigh)) { +				assert(!pim_jp_agg_is_in_list( +					neigh->upstream_jp_agg, up)); +			} +		} +	}  #else -  return; +	return;  #endif  } -void -pim_jp_agg_add_group (struct list *group, struct pim_upstream *up, bool is_join) +void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up, +			  bool is_join)  { -  struct listnode *node, *nnode; -  struct pim_jp_agg_group *jag = NULL; -  struct pim_jp_sources *js = NULL; - -  for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) -    { -      if (jag->group.s_addr == up->sg.grp.s_addr) -        break; -    } - -  if (!jag) -    { -      jag = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof (struct pim_jp_agg_group)); -      jag->group.s_addr = up->sg.grp.s_addr; -      jag->sources = list_new(); -      jag->sources->cmp = pim_jp_agg_src_cmp; -      jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; -      listnode_add_sort (group, jag); -    } - -  for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) -    { -      if (js->up == up) -        break; -    } - -  if (!js) -    { -      js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, sizeof (struct pim_jp_sources)); -      js->up = up; -      js->is_join = is_join; -      listnode_add_sort (jag->sources, js); -    } -  else -    { -      if (js->is_join != is_join) -        { -          listnode_delete(jag->sources, js); -          js->is_join = is_join; -          listnode_add_sort (jag->sources, js); -        } -    } +	struct listnode *node, *nnode; +	struct pim_jp_agg_group *jag = NULL; +	struct pim_jp_sources *js = NULL; + +	for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { +		if (jag->group.s_addr == up->sg.grp.s_addr) +			break; +	} + +	if (!jag) { +		jag = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, +			      sizeof(struct pim_jp_agg_group)); +		jag->group.s_addr = up->sg.grp.s_addr; +		jag->sources = list_new(); +		jag->sources->cmp = pim_jp_agg_src_cmp; +		jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; +		listnode_add_sort(group, jag); +	} + +	for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { +		if (js->up == up) +			break; +	} + +	if (!js) { +		js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, +			     sizeof(struct pim_jp_sources)); +		js->up = up; +		js->is_join = is_join; +		listnode_add_sort(jag->sources, js); +	} else { +		if (js->is_join != is_join) { +			listnode_delete(jag->sources, js); +			js->is_join = is_join; +			listnode_add_sort(jag->sources, js); +		} +	}  } -void -pim_jp_agg_switch_interface (struct pim_rpf *orpf, -                             struct pim_rpf *nrpf, -                             struct pim_upstream *up) +void pim_jp_agg_switch_interface(struct pim_rpf *orpf, struct pim_rpf *nrpf, +				 struct pim_upstream *up)  { -  struct pim_iface_upstream_switch *opius; -  struct pim_iface_upstream_switch *npius; - -  opius = pim_jp_agg_get_interface_upstream_switch_list(orpf); -  npius = pim_jp_agg_get_interface_upstream_switch_list(nrpf); - -  /* -   * RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Messages -   * -   * Transitions from Joined State -   * -   * RPF'(S,G) changes not due to an Assert -   * -   * The upstream (S,G) state machine remains in Joined -   * state. Send Join(S,G) to the new upstream neighbor, which is -   * the new value of RPF'(S,G).  Send Prune(S,G) to the old -   * upstream neighbor, which is the old value of RPF'(S,G).  Set -   * the Join Timer (JT) to expire after t_periodic seconds. -   */ - -  /* send Prune(S,G) to the old upstream neighbor */ -  if (opius) -    pim_jp_agg_add_group (opius->us, up, false); - -  /* send Join(S,G) to the current upstream neighbor */ -  pim_jp_agg_add_group (npius->us, up, true); - +	struct pim_iface_upstream_switch *opius; +	struct pim_iface_upstream_switch *npius; + +	opius = pim_jp_agg_get_interface_upstream_switch_list(orpf); +	npius = pim_jp_agg_get_interface_upstream_switch_list(nrpf); + +	/* +	 * RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Messages +	 * +	 * Transitions from Joined State +	 * +	 * RPF'(S,G) changes not due to an Assert +	 * +	 * The upstream (S,G) state machine remains in Joined +	 * state. Send Join(S,G) to the new upstream neighbor, which is +	 * the new value of RPF'(S,G).  Send Prune(S,G) to the old +	 * upstream neighbor, which is the old value of RPF'(S,G).  Set +	 * the Join Timer (JT) to expire after t_periodic seconds. +	 */ + +	/* send Prune(S,G) to the old upstream neighbor */ +	if (opius) +		pim_jp_agg_add_group(opius->us, up, false); + +	/* send Join(S,G) to the current upstream neighbor */ +	pim_jp_agg_add_group(npius->us, up, true);  } -void -pim_jp_agg_single_upstream_send (struct pim_rpf *rpf, -                                 struct pim_upstream *up, -                                 bool is_join) +void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, +				     struct pim_upstream *up, bool is_join)  { -  static struct list *groups = NULL; -  static struct pim_jp_agg_group jag; -  static struct pim_jp_sources js; +	static struct list *groups = NULL; +	static struct pim_jp_agg_group jag; +	static struct pim_jp_sources js; -  static bool first = true; +	static bool first = true; -  /* skip JP upstream messages if source is directly connected */ -  if (!up || !rpf->source_nexthop.interface || -      pim_if_connected_to_source (rpf->source_nexthop.interface, up->sg.src)) -    return; +	/* skip JP upstream messages if source is directly connected */ +	if (!up || !rpf->source_nexthop.interface || pim_if_connected_to_source( +							     rpf->source_nexthop +								     .interface, +							     up->sg.src)) +		return; -  if (first) -    { -      groups = list_new(); +	if (first) { +		groups = list_new(); -      jag.sources = list_new(); +		jag.sources = list_new(); -      listnode_add(groups, &jag); -      listnode_add(jag.sources, &js); +		listnode_add(groups, &jag); +		listnode_add(jag.sources, &js); -      first = false; -    } +		first = false; +	} -  jag.group.s_addr = up->sg.grp.s_addr; -  js.up = up; -  js.is_join = is_join; +	jag.group.s_addr = up->sg.grp.s_addr; +	js.up = up; +	js.is_join = is_join; -  pim_joinprune_send(rpf, groups); +	pim_joinprune_send(rpf, groups);  } diff --git a/pimd/pim_jp_agg.h b/pimd/pim_jp_agg.h index c3955f32f4..aa21aa9816 100644 --- a/pimd/pim_jp_agg.h +++ b/pimd/pim_jp_agg.h @@ -20,35 +20,31 @@  #ifndef __PIM_JP_AGG_H__  #define __PIM_JP_AGG_H__ -struct pim_jp_sources -{ -  struct pim_upstream *up; -  int is_join; +struct pim_jp_sources { +	struct pim_upstream *up; +	int is_join;  }; -struct pim_jp_agg_group -{ -  struct in_addr group; -  struct list *sources; +struct pim_jp_agg_group { +	struct in_addr group; +	struct list *sources;  }; -void pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore); -int pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up); +void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore); +int pim_jp_agg_is_in_list(struct list *group, struct pim_upstream *up); -void pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag); -int pim_jp_agg_group_list_cmp (void *arg1, void *arg2); +void pim_jp_agg_group_list_free(struct pim_jp_agg_group *jag); +int pim_jp_agg_group_list_cmp(void *arg1, void *arg2); -void pim_jp_agg_clear_group (struct list *group); -void pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up); +void pim_jp_agg_clear_group(struct list *group); +void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up); -void pim_jp_agg_add_group (struct list *group, -                           struct pim_upstream *up, bool is_join); +void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up, +			  bool is_join); -void pim_jp_agg_switch_interface (struct pim_rpf *orpf, -                                  struct pim_rpf *nrpf, -                                  struct pim_upstream *up); +void pim_jp_agg_switch_interface(struct pim_rpf *orpf, struct pim_rpf *nrpf, +				 struct pim_upstream *up); -void pim_jp_agg_single_upstream_send (struct pim_rpf *rpf, -                                      struct pim_upstream *up, -                                      bool is_join); +void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, +				     struct pim_upstream *up, bool is_join);  #endif diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 1f3b29554f..13f4240dba 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -39,20 +39,19 @@  */  static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch)  { -  switch (ch->ifjoin_state) -    { -    case PIM_IFJOIN_NOINFO: -    case PIM_IFJOIN_PRUNE: -    case PIM_IFJOIN_PRUNE_TMP: -    case PIM_IFJOIN_PRUNE_PENDING_TMP: -      return 0; -     break; -    case PIM_IFJOIN_JOIN: -    case PIM_IFJOIN_PRUNE_PENDING: -      return 1; -      break; -    } -  return 0; +	switch (ch->ifjoin_state) { +	case PIM_IFJOIN_NOINFO: +	case PIM_IFJOIN_PRUNE: +	case PIM_IFJOIN_PRUNE_TMP: +	case PIM_IFJOIN_PRUNE_PENDING_TMP: +		return 0; +		break; +	case PIM_IFJOIN_JOIN: +	case PIM_IFJOIN_PRUNE_PENDING: +		return 1; +		break; +	} +	return 0;  }  /* @@ -63,8 +62,8 @@ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch)  */  static int local_receiver_include(const struct pim_ifchannel *ch)  { -  /* local_receiver_include(S,G,I) ? */ -  return ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE; +	/* local_receiver_include(S,G,I) ? */ +	return ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE;  }  /* @@ -75,13 +74,13 @@ static int local_receiver_include(const struct pim_ifchannel *ch)     joins(S,G) =         { all interfaces I such that -         DownstreamJPState(S,G,I) is either Join or Prune-Pending } +	 DownstreamJPState(S,G,I) is either Join or Prune-Pending }    DownstreamJPState(S,G,I) is either Join or Prune-Pending ?  */  int pim_macro_chisin_joins(const struct pim_ifchannel *ch)  { -  return downstream_jpstate_isjoined(ch); +	return downstream_jpstate_isjoined(ch);  }  /* @@ -92,16 +91,16 @@ int pim_macro_chisin_joins(const struct pim_ifchannel *ch)     lost_assert(S,G) =         { all interfaces I such that -         lost_assert(S,G,I) == TRUE } +	 lost_assert(S,G,I) == TRUE }       bool lost_assert(S,G,I) {         if ( RPF_interface(S) == I ) { -          return FALSE +	  return FALSE         } else { -          return ( AssertWinner(S,G,I) != NULL AND -                   AssertWinner(S,G,I) != me  AND -                   (AssertWinnerMetric(S,G,I) is better -                      than spt_assert_metric(S,I) ) +	  return ( AssertWinner(S,G,I) != NULL AND +		   AssertWinner(S,G,I) != me  AND +		   (AssertWinnerMetric(S,G,I) is better +		      than spt_assert_metric(S,I) )         }       } @@ -110,42 +109,40 @@ int pim_macro_chisin_joins(const struct pim_ifchannel *ch)  */  int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch)  { -  struct interface *ifp; -  struct pim_interface *pim_ifp; -  struct pim_assert_metric spt_assert_metric; - -  ifp = ch->interface; -  if (!ifp) { -    zlog_warn("%s: (S,G)=%s: null interface", -	      __PRETTY_FUNCTION__, -	      ch->sg_str); -    return 0; /* false */ -  } - -  /* RPF_interface(S) == I ? */ -  if (ch->upstream->rpf.source_nexthop.interface == ifp) -    return 0; /* false */ - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__, -	      ch->sg_str, ifp->name); -    return 0; /* false */ -  } - -  if (PIM_INADDR_IS_ANY(ch->ifassert_winner)) -    return 0; /* false */ - -  /* AssertWinner(S,G,I) == me ? */ -  if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) -    return 0; /* false */ - -  spt_assert_metric = pim_macro_spt_assert_metric(&ch->upstream->rpf, -						  pim_ifp->primary_address); - -  return pim_assert_metric_better(&ch->ifassert_winner_metric, -				  &spt_assert_metric); +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	struct pim_assert_metric spt_assert_metric; + +	ifp = ch->interface; +	if (!ifp) { +		zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, +			  ch->sg_str); +		return 0; /* false */ +	} + +	/* RPF_interface(S) == I ? */ +	if (ch->upstream->rpf.source_nexthop.interface == ifp) +		return 0; /* false */ + +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ch->sg_str, ifp->name); +		return 0; /* false */ +	} + +	if (PIM_INADDR_IS_ANY(ch->ifassert_winner)) +		return 0; /* false */ + +	/* AssertWinner(S,G,I) == me ? */ +	if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) +		return 0; /* false */ + +	spt_assert_metric = pim_macro_spt_assert_metric( +		&ch->upstream->rpf, pim_ifp->primary_address); + +	return pim_assert_metric_better(&ch->ifassert_winner_metric, +					&spt_assert_metric);  }  /* @@ -153,47 +150,44 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch)     pim_include(S,G) =         { all interfaces I such that: -         ( (I_am_DR( I ) AND lost_assert(S,G,I) == FALSE ) -           OR AssertWinner(S,G,I) == me ) -          AND  local_receiver_include(S,G,I) } +	 ( (I_am_DR( I ) AND lost_assert(S,G,I) == FALSE ) +	   OR AssertWinner(S,G,I) == me ) +	  AND  local_receiver_include(S,G,I) }     AssertWinner(S,G,I) is the IP source address of the Assert(S,G)     packet that won an Assert.  */  int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch)  { -  struct pim_interface *pim_ifp = ch->interface->info; - -  if (!pim_ifp) { -    zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__, -	      ch->sg_str, ch->interface->name); -    return 0; /* false */ -  } - -  /* local_receiver_include(S,G,I) ? */ -  if (!local_receiver_include(ch)) -    return 0; /* false */ -     -  /* OR AssertWinner(S,G,I) == me ? */ -  if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) -    return 1; /* true */ -     -  return ( -	  /* I_am_DR( I ) ? */ -	  PIM_I_am_DR(pim_ifp) -	  && -	  /* lost_assert(S,G,I) == FALSE ? */ -	  (!pim_macro_ch_lost_assert(ch)) -	  ); +	struct pim_interface *pim_ifp = ch->interface->info; + +	if (!pim_ifp) { +		zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); +		return 0; /* false */ +	} + +	/* local_receiver_include(S,G,I) ? */ +	if (!local_receiver_include(ch)) +		return 0; /* false */ + +	/* OR AssertWinner(S,G,I) == me ? */ +	if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) +		return 1; /* true */ + +	return ( +		/* I_am_DR( I ) ? */ +		PIM_I_am_DR(pim_ifp) && +		/* lost_assert(S,G,I) == FALSE ? */ +		(!pim_macro_ch_lost_assert(ch)));  }  int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch)  { -  if (pim_macro_chisin_joins(ch)) -    return 1; /* true */ +	if (pim_macro_chisin_joins(ch)) +		return 1; /* true */ -  return pim_macro_chisin_pim_include(ch); +	return pim_macro_chisin_pim_include(ch);  }  /* @@ -203,9 +197,9 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch)    SPTbit(S,G)==TRUE    AND (RPF_interface(S) != I)    AND (I in ( ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) ) -                 (+) ( pim_include(*,G) (-) pim_exclude(S,G) ) -                 (-) lost_assert(*,G) -                 (+) joins(S,G) (+) pim_include(S,G) ) ) +		 (+) ( pim_include(*,G) (-) pim_exclude(S,G) ) +		 (-) lost_assert(*,G) +		 (+) joins(S,G) (+) pim_include(S,G) ) )    CouldAssert(S,G,I) is true for downstream interfaces that would be in    the inherited_olist(S,G) if (S,G) assert information was not taken @@ -225,25 +219,25 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch)  */  int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch)  { -  struct interface *ifp; +	struct interface *ifp; -  ifp = ch->interface; -  if (!ifp) { -    zlog_warn("%s: (S,G)=%s: null interface", -	      __PRETTY_FUNCTION__, ch->sg_str); -    return 0; /* false */ -  } +	ifp = ch->interface; +	if (!ifp) { +		zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, +			  ch->sg_str); +		return 0; /* false */ +	} -  /* SPTbit(S,G) == TRUE */ -  if (ch->upstream->sptbit == PIM_UPSTREAM_SPTBIT_FALSE) -    return 0; /* false */ +	/* SPTbit(S,G) == TRUE */ +	if (ch->upstream->sptbit == PIM_UPSTREAM_SPTBIT_FALSE) +		return 0; /* false */ -  /* RPF_interface(S) != I ? */ -  if (ch->upstream->rpf.source_nexthop.interface == ifp) -    return 0; /* false */ +	/* RPF_interface(S) != I ? */ +	if (ch->upstream->rpf.source_nexthop.interface == ifp) +		return 0; /* false */ -  /* I in joins(S,G) (+) pim_include(S,G) ? */ -  return pim_macro_chisin_joins_or_include(ch); +	/* I in joins(S,G) (+) pim_include(S,G) ? */ +	return pim_macro_chisin_joins_or_include(ch);  }  /* @@ -260,14 +254,14 @@ int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch)  struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf,  						     struct in_addr ifaddr)  { -  struct pim_assert_metric metric; +	struct pim_assert_metric metric; -  metric.rpt_bit_flag      = 0; -  metric.metric_preference = rpf->source_nexthop.mrib_metric_preference; -  metric.route_metric      = rpf->source_nexthop.mrib_route_metric; -  metric.ip_address        = ifaddr; +	metric.rpt_bit_flag = 0; +	metric.metric_preference = rpf->source_nexthop.mrib_metric_preference; +	metric.route_metric = rpf->source_nexthop.mrib_route_metric; +	metric.ip_address = ifaddr; -  return metric; +	return metric;  }  /* @@ -287,24 +281,26 @@ struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf,      }    }  */ -struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch) +struct pim_assert_metric +pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  pim_ifp = ch->interface->info; +	pim_ifp = ch->interface->info; -  if (pim_ifp) { -    if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { -      return pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); -    } -  } +	if (pim_ifp) { +		if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { +			return pim_macro_spt_assert_metric( +				&ch->upstream->rpf, pim_ifp->primary_address); +		} +	} -  return qpim_infinite_assert_metric; +	return qpim_infinite_assert_metric;  }  /*    RFC 4601 4.2.  Data Packet Forwarding Rules -   +    Macro:    inherited_olist(S,G) =      inherited_olist(S,G,rpt) (+) @@ -312,10 +308,10 @@ struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifc  */  static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch)  { -  if (pim_macro_ch_lost_assert(ch)) -    return 0; /* false */ +	if (pim_macro_ch_lost_assert(ch)) +		return 0; /* false */ -  return pim_macro_chisin_joins_or_include(ch); +	return pim_macro_chisin_joins_or_include(ch);  }  /* @@ -324,7 +320,7 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch)    Additionally, the Packet forwarding rules of Section 4.2 can be    simplified in a PIM-SSM-only router: -   +    iif is the incoming interface of the packet.    oiflist = NULL    if (iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined) { @@ -334,7 +330,7 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch)    }    oiflist = oiflist (-) iif    forward packet on all interfaces in oiflist -   +    Macro:    inherited_olist(S,G) =      joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) @@ -349,16 +345,16 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch)  */  int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch)  { -  if (ch->upstream->join_state == PIM_UPSTREAM_NOTJOINED) { -    /* oiflist is NULL */ -    return 0; /* false */ -  } +	if (ch->upstream->join_state == PIM_UPSTREAM_NOTJOINED) { +		/* oiflist is NULL */ +		return 0; /* false */ +	} -  /* oiflist = oiflist (-) iif */ -  if (ch->interface == ch->upstream->rpf.source_nexthop.interface) -    return 0; /* false */ +	/* oiflist = oiflist (-) iif */ +	if (ch->interface == ch->upstream->rpf.source_nexthop.interface) +		return 0; /* false */ -  return pim_macro_chisin_inherited_olist(ch); +	return pim_macro_chisin_inherited_olist(ch);  }  /* @@ -380,45 +376,45 @@ int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch)  */  int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch)  { -  struct pim_interface *pim_ifp; -  struct interface *ifp; - -  ifp = ch->interface; -  if (!ifp) { -    zlog_warn("%s: (S,G)=%s: null interface", -	      __PRETTY_FUNCTION__, ch->sg_str); -    return 0; /* false */ -  } - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", -	      __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); -    return 0; /* false */ -  } - -  /* I in joins(S,G) ? */ -  if (pim_macro_chisin_joins(ch)) -    return 1; /* true */ - -  /* local_receiver_include(S,G,I) ? */ -  if (local_receiver_include(ch)) { -    /* I_am_DR(I) ? */ -    if (PIM_I_am_DR(pim_ifp)) -      return 1; /* true */ - -    /* AssertWinner(S,G,I) == me ? */ -    if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) -      return 1; /* true */ -  } - -  /* RPF_interface(S) == I ? */ -  if (ch->upstream->rpf.source_nexthop.interface == ifp) { -    /* JoinDesired(S,G) ? */ -    if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags)) -      return 1; /* true */ -  } - -  return 0; /* false */ +	struct pim_interface *pim_ifp; +	struct interface *ifp; + +	ifp = ch->interface; +	if (!ifp) { +		zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, +			  ch->sg_str); +		return 0; /* false */ +	} + +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", +			  __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); +		return 0; /* false */ +	} + +	/* I in joins(S,G) ? */ +	if (pim_macro_chisin_joins(ch)) +		return 1; /* true */ + +	/* local_receiver_include(S,G,I) ? */ +	if (local_receiver_include(ch)) { +		/* I_am_DR(I) ? */ +		if (PIM_I_am_DR(pim_ifp)) +			return 1; /* true */ + +		/* AssertWinner(S,G,I) == me ? */ +		if (ch->ifassert_winner.s_addr +		    == pim_ifp->primary_address.s_addr) +			return 1; /* true */ +	} + +	/* RPF_interface(S) == I ? */ +	if (ch->upstream->rpf.source_nexthop.interface == ifp) { +		/* JoinDesired(S,G) ? */ +		if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags)) +			return 1; /* true */ +	} + +	return 0; /* false */  } - diff --git a/pimd/pim_macro.h b/pimd/pim_macro.h index e07b2ece94..f310e244e8 100644 --- a/pimd/pim_macro.h +++ b/pimd/pim_macro.h @@ -34,7 +34,8 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch);  int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch);  struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf,  						     struct in_addr ifaddr); -struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch); +struct pim_assert_metric +pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch);  int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch);  int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch); diff --git a/pimd/pim_main.c b/pimd/pim_main.c index a80059535d..b8e6d8ad3d 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -20,7 +20,7 @@  #include <zebra.h>  #include "log.h" -#include "privs.h"  +#include "privs.h"  #include "version.h"  #include <getopt.h>  #include "command.h" @@ -49,115 +49,109 @@  extern struct host host; -struct option longopts[] = { -  { 0 } -}; +struct option longopts[] = {{0}};  /* pimd privileges */ -zebra_capabilities_t _caps_p [] =  -{ -  ZCAP_NET_ADMIN, -  ZCAP_SYS_ADMIN, -  ZCAP_NET_RAW, -  ZCAP_BIND, +zebra_capabilities_t _caps_p[] = { +	ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, ZCAP_NET_RAW, ZCAP_BIND,  };  /* pimd privileges to run with */ -struct zebra_privs_t pimd_privs = -{ +struct zebra_privs_t pimd_privs = {  #if defined(FRR_USER) && defined(FRR_GROUP) -  .user = FRR_USER, -  .group = FRR_GROUP, +	.user = FRR_USER, +	.group = FRR_GROUP,  #endif  #ifdef VTY_GROUP -  .vty_group = VTY_GROUP, +	.vty_group = VTY_GROUP,  #endif -  .caps_p = _caps_p, -  .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]), -  .cap_num_i = 0 -}; - -FRR_DAEMON_INFO(pimd, PIM, -	.vty_port = PIMD_VTY_PORT, - -	.proghelp = "Implementation of the PIM routing protocol.", - -	.signals = pimd_signals, -	.n_signals = 4 /* XXX array_size(pimd_signals) XXX*/, +	.caps_p = _caps_p, +	.cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]), +	.cap_num_i = 0}; -	.privs = &pimd_privs, -) +FRR_DAEMON_INFO(pimd, PIM, .vty_port = PIMD_VTY_PORT, +		.proghelp = "Implementation of the PIM routing protocol.", -int main(int argc, char** argv, char** envp) { -  frr_preinit(&pimd_di, argc, argv); -  frr_opt_add("", longopts, ""); +		.signals = pimd_signals, +		.n_signals = 4 /* XXX array_size(pimd_signals) XXX*/, -  /* this while just reads the options */ -  while (1) { -    int opt; +		.privs = &pimd_privs, ) -    opt = frr_getopt(argc, argv, NULL); -    if (opt == EOF) -      break; -     -    switch (opt) { -    case 0: -      break; -    default: -      frr_help_exit (1); -      break; -    } -  } - -  master = frr_init(); - -  /*  -   * Initializations -   */ -  pim_vrf_init (); -  access_list_init(); -  prefix_list_init (); -  prefix_list_add_hook (pim_prefix_list_update); -  prefix_list_delete_hook (pim_prefix_list_update); - -  pim_route_map_init (); -  pim_init(); -  pim_msdp_init (master); - -  /* -   * Initialize zclient "update" and "lookup" sockets -   */ -  pim_zebra_init(); -  pim_bfd_init (); - -  frr_config_fork(); +int main(int argc, char **argv, char **envp) +{ +	frr_preinit(&pimd_di, argc, argv); +	frr_opt_add("", longopts, ""); + +	/* this while just reads the options */ +	while (1) { +		int opt; + +		opt = frr_getopt(argc, argv, NULL); + +		if (opt == EOF) +			break; + +		switch (opt) { +		case 0: +			break; +		default: +			frr_help_exit(1); +			break; +		} +	} + +	master = frr_init(); + +	/* +	 * Initializations +	 */ +	pim_vrf_init(); +	access_list_init(); +	prefix_list_init(); +	prefix_list_add_hook(pim_prefix_list_update); +	prefix_list_delete_hook(pim_prefix_list_update); + +	pim_route_map_init(); +	pim_init(); +	pim_msdp_init(master); + +	/* +	 * Initialize zclient "update" and "lookup" sockets +	 */ +	pim_zebra_init(); +	pim_bfd_init(); + +	frr_config_fork();  #ifdef PIM_DEBUG_BYDEFAULT -  zlog_notice("PIM_DEBUG_BYDEFAULT: Enabling all debug commands"); -  PIM_DO_DEBUG_PIM_EVENTS; -  PIM_DO_DEBUG_PIM_PACKETS; -  PIM_DO_DEBUG_PIM_TRACE; -  PIM_DO_DEBUG_IGMP_EVENTS; -  PIM_DO_DEBUG_IGMP_PACKETS; -  PIM_DO_DEBUG_IGMP_TRACE; -  PIM_DO_DEBUG_ZEBRA; +	zlog_notice("PIM_DEBUG_BYDEFAULT: Enabling all debug commands"); +	PIM_DO_DEBUG_PIM_EVENTS; +	PIM_DO_DEBUG_PIM_PACKETS; +	PIM_DO_DEBUG_PIM_TRACE; +	PIM_DO_DEBUG_IGMP_EVENTS; +	PIM_DO_DEBUG_IGMP_PACKETS; +	PIM_DO_DEBUG_IGMP_TRACE; +	PIM_DO_DEBUG_ZEBRA;  #endif  #ifdef PIM_CHECK_RECV_IFINDEX_SANITY -  zlog_notice("PIM_CHECK_RECV_IFINDEX_SANITY: will match sock/recv ifindex"); +	zlog_notice( +		"PIM_CHECK_RECV_IFINDEX_SANITY: will match sock/recv ifindex");  #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH -  zlog_notice("PIM_REPORT_RECV_IFINDEX_MISMATCH: will report sock/recv ifindex mismatch"); +	zlog_notice( +		"PIM_REPORT_RECV_IFINDEX_MISMATCH: will report sock/recv ifindex mismatch");  #endif  #endif  #ifdef PIM_UNEXPECTED_KERNEL_UPCALL -  zlog_notice("PIM_UNEXPECTED_KERNEL_UPCALL: report unexpected kernel upcall"); +	zlog_notice( +		"PIM_UNEXPECTED_KERNEL_UPCALL: report unexpected kernel upcall");  #endif -  frr_run(master); +	frr_run(master); -  /* never reached */ -  return 0; +	/* never reached */ +	return 0;  } diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index d18b7f0c8e..dff16c4165 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -26,29 +26,29 @@  #include "pim_memory.h"  DEFINE_MGROUP(PIMD, "pimd") -DEFINE_MTYPE(PIMD, PIM_CHANNEL_OIL,       "PIM SSM (S,G) channel OIL") -DEFINE_MTYPE(PIMD, PIM_INTERFACE,         "PIM interface") -DEFINE_MTYPE(PIMD, PIM_IGMP_JOIN,         "PIM interface IGMP static join") -DEFINE_MTYPE(PIMD, PIM_IGMP_SOCKET,       "PIM interface IGMP socket") -DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP,        "PIM interface IGMP group") +DEFINE_MTYPE(PIMD, PIM_CHANNEL_OIL, "PIM SSM (S,G) channel OIL") +DEFINE_MTYPE(PIMD, PIM_INTERFACE, "PIM interface") +DEFINE_MTYPE(PIMD, PIM_IGMP_JOIN, "PIM interface IGMP static join") +DEFINE_MTYPE(PIMD, PIM_IGMP_SOCKET, "PIM interface IGMP socket") +DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP, "PIM interface IGMP group")  DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP_SOURCE, "PIM interface IGMP source") -DEFINE_MTYPE(PIMD, PIM_NEIGHBOR,          "PIM interface neighbor") -DEFINE_MTYPE(PIMD, PIM_IFCHANNEL,         "PIM interface (S,G) state") -DEFINE_MTYPE(PIMD, PIM_UPSTREAM,          "PIM upstream (S,G) state") -DEFINE_MTYPE(PIMD, PIM_SSMPINGD,          "PIM sspimgd socket") -DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE,      "PIM Static Route") -DEFINE_MTYPE(PIMD, PIM_BR,                "PIM Bridge Router info") -DEFINE_MTYPE(PIMD, PIM_RP,                "PIM RP info") -DEFINE_MTYPE(PIMD, PIM_FILTER_NAME,       "PIM RP filter info") -DEFINE_MTYPE(PIMD, PIM_MSDP_PEER,         "PIM MSDP peer") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME,      "PIM MSDP mesh-group name") -DEFINE_MTYPE(PIMD, PIM_MSDP_SA,           "PIM MSDP source-active cache") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG,           "PIM MSDP mesh group") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR,       "PIM MSDP mesh group mbr") -DEFINE_MTYPE(PIMD, PIM_SEC_ADDR,          "PIM secondary address") -DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP,      "PIM JP AGG Group") -DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE,     "PIM JP AGG Source") -DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE,      "PIM global state") -DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE,     "PIM nexthop cache state") -DEFINE_MTYPE(PIMD, PIM_SSM_INFO,          "PIM SSM configuration") -DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME,    "PIM SPT Prefix List Name") +DEFINE_MTYPE(PIMD, PIM_NEIGHBOR, "PIM interface neighbor") +DEFINE_MTYPE(PIMD, PIM_IFCHANNEL, "PIM interface (S,G) state") +DEFINE_MTYPE(PIMD, PIM_UPSTREAM, "PIM upstream (S,G) state") +DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") +DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") +DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") +DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") +DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") +DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name") +DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") +DEFINE_MTYPE(PIMD, PIM_SEC_ADDR, "PIM secondary address") +DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP, "PIM JP AGG Group") +DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source") +DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state") +DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") +DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration") +DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name") diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 01747268a3..a92b01ca00 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -47,358 +47,360 @@ static void mroute_read_on(void);  static int pim_mroute_set(int fd, int enable)  { -  int err; -  int opt = enable ? MRT_INIT : MRT_DONE; -  socklen_t opt_len = sizeof(opt); -  int rcvbuf = 1024 * 1024 * 8; -  long flags; - -  err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); -  if (err) { -    zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", -	      __FILE__, __PRETTY_FUNCTION__, -	      fd, enable ? "MRT_INIT" : "MRT_DONE", opt, errno, safe_strerror(errno)); -    return -1; -  } - -  err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); -  if (err) { -    zlog_warn("%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", -	      __PRETTY_FUNCTION__, fd, rcvbuf, errno, safe_strerror(errno)); -  } - -  flags = fcntl(fd, F_GETFL, 0); -  if (flags < 0) -    { -      zlog_warn("Could not get flags on socket fd:%d %d %s", -		fd, errno, safe_strerror(errno)); -      close (fd); -      return -1; -    } -  if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) -    { -      zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", -		fd, errno, safe_strerror(errno)); -      close(fd); -      return -1; -    } +	int err; +	int opt = enable ? MRT_INIT : MRT_DONE; +	socklen_t opt_len = sizeof(opt); +	int rcvbuf = 1024 * 1024 * 8; +	long flags; + +	err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); +	if (err) { +		zlog_warn( +			"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", +			__FILE__, __PRETTY_FUNCTION__, fd, +			enable ? "MRT_INIT" : "MRT_DONE", opt, errno, +			safe_strerror(errno)); +		return -1; +	} -  if (enable) -    { +	err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); +	if (err) { +		zlog_warn( +			"%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", +			__PRETTY_FUNCTION__, fd, rcvbuf, errno, +			safe_strerror(errno)); +	} + +	flags = fcntl(fd, F_GETFL, 0); +	if (flags < 0) { +		zlog_warn("Could not get flags on socket fd:%d %d %s", fd, +			  errno, safe_strerror(errno)); +		close(fd); +		return -1; +	} +	if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { +		zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", fd, +			  errno, safe_strerror(errno)); +		close(fd); +		return -1; +	} + +	if (enable) {  #if defined linux -      int upcalls = IGMPMSG_WRVIFWHOLE; -      opt = MRT_PIM; -     -      err = setsockopt (fd, IPPROTO_IP, opt, &upcalls, sizeof (upcalls)); -      if (err) -        { -          zlog_warn ("Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", -		     errno, safe_strerror (errno)); -          return -1; -        } +		int upcalls = IGMPMSG_WRVIFWHOLE; +		opt = MRT_PIM; + +		err = setsockopt(fd, IPPROTO_IP, opt, &upcalls, +				 sizeof(upcalls)); +		if (err) { +			zlog_warn( +				"Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", +				errno, safe_strerror(errno)); +			return -1; +		}  #else -      zlog_warn ("PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); +		zlog_warn( +			"PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall");  #endif -    } -   -  return 0; +	} + +	return 0;  }  static const char *igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = { -  "<unknown_upcall?>", -  "NOCACHE", -  "WRONGVIF", -  "WHOLEPKT", -  "WRVIFWHOLE" }; - -static int -pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg) +	"<unknown_upcall?>", "NOCACHE", "WRONGVIF", "WHOLEPKT", "WRVIFWHOLE"}; + +static int pim_mroute_msg_nocache(int fd, struct interface *ifp, +				  const struct igmpmsg *msg)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct pim_upstream *up; -  struct pim_rpf *rpg; -  struct prefix_sg sg; - -  rpg = RP(msg->im_dst); -  /* -   * If the incoming interface is unknown OR -   * the Interface type is SSM we don't need to -   * do anything here -   */ -  if ((pim_rpf_addr_is_inaddr_none (rpg)) || -      (!pim_ifp) || -      (!(PIM_I_am_DR(pim_ifp)))) -    { -      if (PIM_DEBUG_MROUTE_DETAIL) -	zlog_debug ("%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", -		    __PRETTY_FUNCTION__); -      return 0; -    } +	struct pim_interface *pim_ifp = ifp->info; +	struct pim_upstream *up; +	struct pim_rpf *rpg; +	struct prefix_sg sg; + +	rpg = RP(msg->im_dst); +	/* +	 * If the incoming interface is unknown OR +	 * the Interface type is SSM we don't need to +	 * do anything here +	 */ +	if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) +	    || (!(PIM_I_am_DR(pim_ifp)))) { +		if (PIM_DEBUG_MROUTE_DETAIL) +			zlog_debug( +				"%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", +				__PRETTY_FUNCTION__); +		return 0; +	} -  /* -   * If we've received a multicast packet that isn't connected to -   * us -   */ -  if (!pim_if_connected_to_source (ifp, msg->im_src)) -    { -      if (PIM_DEBUG_MROUTE_DETAIL) -       zlog_debug ("%s: Received incoming packet that doesn't originate on our seg", -		   __PRETTY_FUNCTION__); -      return 0; -    } +	/* +	 * If we've received a multicast packet that isn't connected to +	 * us +	 */ +	if (!pim_if_connected_to_source(ifp, msg->im_src)) { +		if (PIM_DEBUG_MROUTE_DETAIL) +			zlog_debug( +				"%s: Received incoming packet that doesn't originate on our seg", +				__PRETTY_FUNCTION__); +		return 0; +	} -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = msg->im_src; -  sg.grp = msg->im_dst; +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = msg->im_src; +	sg.grp = msg->im_dst; + +	up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, +				      __PRETTY_FUNCTION__); +	if (!up) { +		if (PIM_DEBUG_MROUTE) { +			zlog_debug( +				"%s: Failure to add upstream information for %s", +				__PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); +		} +		return 0; +	} -  up = pim_upstream_find_or_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); -  if (!up) -    { -      if (PIM_DEBUG_MROUTE) -        { -          zlog_debug("%s: Failure to add upstream information for %s", -                     __PRETTY_FUNCTION__, -                     pim_str_sg_dump (&sg)); -        } -      return 0; -    } +	/* +	 * I moved this debug till after the actual add because +	 * I want to take advantage of the up->sg_str being filled in. +	 */ +	if (PIM_DEBUG_MROUTE) { +		zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", +			   __PRETTY_FUNCTION__, up->sg_str); +	} -  /* -   * I moved this debug till after the actual add because -   * I want to take advantage of the up->sg_str being filled in. -   */ -  if (PIM_DEBUG_MROUTE) { -    zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", -	       __PRETTY_FUNCTION__, up->sg_str); -  } - -  PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); -  pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - -  up->channel_oil->cc.pktcnt++; -  PIM_UPSTREAM_FLAG_SET_FHR(up->flags); -  // resolve mfcc_parent prior to mroute_add in channel_add_oif -  if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) -    { -      int vif_index = 0; -      vif_index = -        pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop. -                                         interface->ifindex); -      up->channel_oil->oil.mfcc_parent = vif_index; -    } -  pim_register_join (up); +	PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); +	pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + +	up->channel_oil->cc.pktcnt++; +	PIM_UPSTREAM_FLAG_SET_FHR(up->flags); +	// resolve mfcc_parent prior to mroute_add in channel_add_oif +	if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) { +		int vif_index = 0; +		vif_index = pim_if_find_vifindex_by_ifindex( +			up->rpf.source_nexthop.interface->ifindex); +		up->channel_oil->oil.mfcc_parent = vif_index; +	} +	pim_register_join(up); -  return 0; +	return 0;  } -static int -pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, +				   const char *buf)  { -  struct pim_interface *pim_ifp; -  struct prefix_sg sg; -  struct pim_rpf *rpg; -  const struct ip *ip_hdr; -  struct pim_upstream *up; - -  ip_hdr = (const struct ip *)buf; - -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = ip_hdr->ip_src; -  sg.grp = ip_hdr->ip_dst; - -  up = pim_upstream_find(&sg); -  if (!up) { -    struct prefix_sg star = sg; -    star.src.s_addr = INADDR_ANY; - -    up = pim_upstream_find(&star); - -    if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) -      { -	up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); -        if (!up) -          { -            if (PIM_DEBUG_MROUTE) -              zlog_debug ("%s: Unable to create upstream information for %s", -                          __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); -            return 0; -          } -	pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); -	pim_upstream_inherited_olist (up); -	pim_upstream_switch(up, PIM_UPSTREAM_JOINED); - -	if (PIM_DEBUG_MROUTE) -	  zlog_debug ("%s: Creating %s upstream on LHR", -		      __PRETTY_FUNCTION__, up->sg_str); -        return 0; -      } -    if (PIM_DEBUG_MROUTE_DETAIL) { -      zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", -		 __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); -    } -    return 0; -  } +	struct pim_interface *pim_ifp; +	struct prefix_sg sg; +	struct pim_rpf *rpg; +	const struct ip *ip_hdr; +	struct pim_upstream *up; + +	ip_hdr = (const struct ip *)buf; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = ip_hdr->ip_src; +	sg.grp = ip_hdr->ip_dst; + +	up = pim_upstream_find(&sg); +	if (!up) { +		struct prefix_sg star = sg; +		star.src.s_addr = INADDR_ANY; + +		up = pim_upstream_find(&star); + +		if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) { +			up = pim_upstream_add(&sg, ifp, +					      PIM_UPSTREAM_FLAG_MASK_SRC_LHR, +					      __PRETTY_FUNCTION__); +			if (!up) { +				if (PIM_DEBUG_MROUTE) +					zlog_debug( +						"%s: Unable to create upstream information for %s", +						__PRETTY_FUNCTION__, +						pim_str_sg_dump(&sg)); +				return 0; +			} +			pim_upstream_keep_alive_timer_start( +				up, qpim_keep_alive_time); +			pim_upstream_inherited_olist(up); +			pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + +			if (PIM_DEBUG_MROUTE) +				zlog_debug("%s: Creating %s upstream on LHR", +					   __PRETTY_FUNCTION__, up->sg_str); +			return 0; +		} +		if (PIM_DEBUG_MROUTE_DETAIL) { +			zlog_debug( +				"%s: Unable to find upstream channel WHOLEPKT%s", +				__PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); +		} +		return 0; +	} -  pim_ifp = up->rpf.source_nexthop.interface->info; +	pim_ifp = up->rpf.source_nexthop.interface->info; -  rpg = RP(sg.grp); +	rpg = RP(sg.grp); -  if ((pim_rpf_addr_is_inaddr_none (rpg)) || -      (!pim_ifp) || -      (!(PIM_I_am_DR(pim_ifp)))) { -    if (PIM_DEBUG_MROUTE) { -      zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__); -    } -    return 0; -  } +	if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) +	    || (!(PIM_I_am_DR(pim_ifp)))) { +		if (PIM_DEBUG_MROUTE) { +			zlog_debug("%s: Failed Check send packet", +				   __PRETTY_FUNCTION__); +		} +		return 0; +	} -  /* -   * If we've received a register suppress -   */ -  if (!up->t_rs_timer) -    { -      if (pim_is_grp_ssm (sg.grp)) -        { -          if (PIM_DEBUG_PIM_REG) -            zlog_debug ("%s register forward skipped as group is SSM", -                        pim_str_sg_dump (&sg)); -          return 0; -        } -      pim_register_send((uint8_t *)buf + sizeof(struct ip), -                        ntohs (ip_hdr->ip_len) - sizeof (struct ip), -                        pim_ifp->primary_address, rpg, 0, up); -    } -  return 0; +	/* +	 * If we've received a register suppress +	 */ +	if (!up->t_rs_timer) { +		if (pim_is_grp_ssm(sg.grp)) { +			if (PIM_DEBUG_PIM_REG) +				zlog_debug( +					"%s register forward skipped as group is SSM", +					pim_str_sg_dump(&sg)); +			return 0; +		} +		pim_register_send((uint8_t *)buf + sizeof(struct ip), +				  ntohs(ip_hdr->ip_len) - sizeof(struct ip), +				  pim_ifp->primary_address, rpg, 0, up); +	} +	return 0;  } -static int -pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg) +static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, +				   const struct igmpmsg *msg)  { -  struct pim_ifchannel *ch; -  struct pim_interface *pim_ifp; -  struct prefix_sg sg; +	struct pim_ifchannel *ch; +	struct pim_interface *pim_ifp; +	struct prefix_sg sg; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = msg->im_src; +	sg.grp = msg->im_dst; + +	/* +	  Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. + +	  RFC 4601 4.8.2.  PIM-SSM-Only Routers + +	  iif is the incoming interface of the packet. +	  if (iif is in inherited_olist(S,G)) { +	  send Assert(S,G) on iif +	  } +	*/ + +	if (!ifp) { +		if (PIM_DEBUG_MROUTE) +			zlog_debug( +				"%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", +				__PRETTY_FUNCTION__, pim_str_sg_dump(&sg), +				msg->im_vif); +		return -1; +	} -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = msg->im_src; -  sg.grp = msg->im_dst; +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		if (PIM_DEBUG_MROUTE) +			zlog_debug( +				"%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", +				__PRETTY_FUNCTION__, pim_str_sg_dump(&sg), +				ifp->name); +		return -2; +	} -  /* -    Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. +	ch = pim_ifchannel_find(ifp, &sg); +	if (!ch) { +		struct prefix_sg star_g = sg; +		if (PIM_DEBUG_MROUTE) +			zlog_debug( +				"%s: WRONGVIF (S,G)=%s could not find channel on interface %s", +				__PRETTY_FUNCTION__, pim_str_sg_dump(&sg), +				ifp->name); + +		star_g.src.s_addr = INADDR_ANY; +		ch = pim_ifchannel_find(ifp, &star_g); +		if (!ch) { +			if (PIM_DEBUG_MROUTE) +				zlog_debug( +					"%s: WRONGVIF (*,G)=%s could not find channel on interface %s", +					__PRETTY_FUNCTION__, +					pim_str_sg_dump(&star_g), ifp->name); +			return -3; +		} +	} -    RFC 4601 4.8.2.  PIM-SSM-Only Routers +	/* +	  RFC 4601: 4.6.1.  (S,G) Assert Message State Machine + +	  Transitions from NoInfo State + +	  An (S,G) data packet arrives on interface I, AND +	  CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an +	  downstream interface that is in our (S,G) outgoing interface +	  list.  We optimistically assume that we will be the assert +	  winner for this (S,G), and so we transition to the "I am Assert +	  Winner" state and perform Actions A1 (below), which will +	  initiate the assert negotiation for (S,G). +	*/ + +	if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { +		if (PIM_DEBUG_MROUTE) { +			zlog_debug( +				"%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", +				__PRETTY_FUNCTION__, ch->sg_str, ifp->name); +		} +		return -4; +	} -    iif is the incoming interface of the packet. -    if (iif is in inherited_olist(S,G)) { -    send Assert(S,G) on iif -    } -  */ - -  if (!ifp) { -    if (PIM_DEBUG_MROUTE) -      zlog_debug("%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", -		 __PRETTY_FUNCTION__, -		 pim_str_sg_dump (&sg), msg->im_vif); -    return -1; -  } - -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    if (PIM_DEBUG_MROUTE) -      zlog_debug("%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", -		 __PRETTY_FUNCTION__, -		 pim_str_sg_dump (&sg), ifp->name); -    return -2; -  } - -  ch = pim_ifchannel_find(ifp, &sg); -  if (!ch) { -    struct prefix_sg star_g = sg; -    if (PIM_DEBUG_MROUTE) -      zlog_debug("%s: WRONGVIF (S,G)=%s could not find channel on interface %s", -		 __PRETTY_FUNCTION__, -		 pim_str_sg_dump(&sg), ifp->name); - -    star_g.src.s_addr = INADDR_ANY; -    ch = pim_ifchannel_find(ifp, &star_g); -    if (!ch) { -      if (PIM_DEBUG_MROUTE) -	zlog_debug("%s: WRONGVIF (*,G)=%s could not find channel on interface %s", -		   __PRETTY_FUNCTION__, -		   pim_str_sg_dump(&star_g), ifp->name); -      return -3; -    } -  } - -  /* -    RFC 4601: 4.6.1.  (S,G) Assert Message State Machine - -    Transitions from NoInfo State - -    An (S,G) data packet arrives on interface I, AND -    CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an -    downstream interface that is in our (S,G) outgoing interface -    list.  We optimistically assume that we will be the assert -    winner for this (S,G), and so we transition to the "I am Assert -    Winner" state and perform Actions A1 (below), which will -    initiate the assert negotiation for (S,G). -  */ - -  if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { -    if (PIM_DEBUG_MROUTE) { -      zlog_debug("%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", -		 __PRETTY_FUNCTION__, -		 ch->sg_str, ifp->name); -    } -    return -4; -  } - -  if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { -    if (PIM_DEBUG_MROUTE) { -      zlog_debug("%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", -		 __PRETTY_FUNCTION__, -		 ch->sg_str, ifp->name); -    } -    return -5; -  } - -  if (assert_action_a1(ch)) { -    if (PIM_DEBUG_MROUTE) { -      zlog_debug("%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", -		 __PRETTY_FUNCTION__, -		 ch->sg_str, ifp->name); -    } -    return -6; -  } +	if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { +		if (PIM_DEBUG_MROUTE) { +			zlog_debug( +				"%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", +				__PRETTY_FUNCTION__, ch->sg_str, ifp->name); +		} +		return -5; +	} + +	if (assert_action_a1(ch)) { +		if (PIM_DEBUG_MROUTE) { +			zlog_debug( +				"%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", +				__PRETTY_FUNCTION__, ch->sg_str, ifp->name); +		} +		return -6; +	} -  return 0; +	return 0;  } -static int -pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, +				     const char *buf)  { -  const struct ip *ip_hdr = (const struct ip *)buf; -  struct pim_interface *pim_ifp; -  struct pim_ifchannel *ch; -  struct pim_upstream *up; -  struct prefix_sg star_g; -  struct prefix_sg sg; -  struct channel_oil *oil; - -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = ip_hdr->ip_src; -  sg.grp = ip_hdr->ip_dst; - -  ch = pim_ifchannel_find(ifp, &sg); -  if (ch) -    { -      if (PIM_DEBUG_MROUTE) -	zlog_debug ("WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", -		    ch->sg_str, ifp->name); -      return -1; -    } +	const struct ip *ip_hdr = (const struct ip *)buf; +	struct pim_interface *pim_ifp; +	struct pim_ifchannel *ch; +	struct pim_upstream *up; +	struct prefix_sg star_g; +	struct prefix_sg sg; +	struct channel_oil *oil; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = ip_hdr->ip_src; +	sg.grp = ip_hdr->ip_dst; + +	ch = pim_ifchannel_find(ifp, &sg); +	if (ch) { +		if (PIM_DEBUG_MROUTE) +			zlog_debug( +				"WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", +				ch->sg_str, ifp->name); +		return -1; +	} -  star_g = sg; -  star_g.src.s_addr = INADDR_ANY; +	star_g = sg; +	star_g.src.s_addr = INADDR_ANY;  #if 0    ch = pim_ifchannel_find(ifp, &star_g);    if (ch) @@ -410,290 +412,313 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf)      }  #endif -  up = pim_upstream_find (&sg); -  if (up) -    { -      struct pim_upstream *parent; -      struct pim_nexthop source; -      struct pim_rpf *rpf = RP (sg.grp); -      if (!rpf || !rpf->source_nexthop.interface) -        return 0; - -      /* -       * If we have received a WRVIFWHOLE and are at this -       * point, we could be receiving the packet on the *,G -       * tree, let's check and if so we can safely drop -       * it. -       */ -      parent = pim_upstream_find (&star_g); -      if (parent && parent->rpf.source_nexthop.interface == ifp) -        return 0; - -      pim_ifp = rpf->source_nexthop.interface->info; - -      memset (&source, 0, sizeof (source)); -      /* -       * If we are the fhr that means we are getting a callback during -       * the pimreg period, so I believe we can ignore this packet -       */ -      if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) -	{ -	  //No if channel, but upstream we are at the RP. -	  if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) -	    pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); -          if (!up->channel_oil) -            up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); -          pim_upstream_inherited_olist (up); -          if (!up->channel_oil->installed) -            pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); -	  pim_upstream_set_sptbit (up, ifp); -	} -      else -	{ -	  if (I_am_RP (up->sg.grp)) -	    { -	      if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) -		pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); -	      up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; -	    } -	  pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); -	  pim_upstream_inherited_olist (up); -	  pim_mroute_msg_wholepkt (fd, ifp, buf); -	} -      return 0; -    } +	up = pim_upstream_find(&sg); +	if (up) { +		struct pim_upstream *parent; +		struct pim_nexthop source; +		struct pim_rpf *rpf = RP(sg.grp); +		if (!rpf || !rpf->source_nexthop.interface) +			return 0; + +		/* +		 * If we have received a WRVIFWHOLE and are at this +		 * point, we could be receiving the packet on the *,G +		 * tree, let's check and if so we can safely drop +		 * it. +		 */ +		parent = pim_upstream_find(&star_g); +		if (parent && parent->rpf.source_nexthop.interface == ifp) +			return 0; + +		pim_ifp = rpf->source_nexthop.interface->info; + +		memset(&source, 0, sizeof(source)); +		/* +		 * If we are the fhr that means we are getting a callback during +		 * the pimreg period, so I believe we can ignore this packet +		 */ +		if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) { +			// No if channel, but upstream we are at the RP. +			if (pim_nexthop_lookup(&source, up->upstream_register, +					       0) +			    == 0) +				pim_register_stop_send(source.interface, &sg, +						       pim_ifp->primary_address, +						       up->upstream_register); +			if (!up->channel_oil) +				up->channel_oil = pim_channel_oil_add( +					&sg, pim_ifp->mroute_vif_index); +			pim_upstream_inherited_olist(up); +			if (!up->channel_oil->installed) +				pim_mroute_add(up->channel_oil, +					       __PRETTY_FUNCTION__); +			pim_upstream_set_sptbit(up, ifp); +		} else { +			if (I_am_RP(up->sg.grp)) { +				if (pim_nexthop_lookup(&source, +						       up->upstream_register, 0) +				    == 0) +					pim_register_stop_send( +						source.interface, &sg, +						pim_ifp->primary_address, +						up->upstream_register); +				up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; +			} +			pim_upstream_keep_alive_timer_start( +				up, qpim_keep_alive_time); +			pim_upstream_inherited_olist(up); +			pim_mroute_msg_wholepkt(fd, ifp, buf); +		} +		return 0; +	} -  pim_ifp = ifp->info; -  oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); -  if (!oil->installed) -    pim_mroute_add (oil, __PRETTY_FUNCTION__); -  if (pim_if_connected_to_source (ifp, sg.src)) -    { -      up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); -      if (!up) -	{ -	  if (PIM_DEBUG_MROUTE) -	    zlog_debug ("%s: WRONGVIF%s unable to create upstream on interface", -			pim_str_sg_dump (&sg), ifp->name); -	  return -2; -	} -      PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); -      pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); -      up->channel_oil = oil; -      up->channel_oil->cc.pktcnt++; -      pim_register_join (up); -      pim_upstream_inherited_olist (up); - -      // Send the packet to the RP -      pim_mroute_msg_wholepkt (fd, ifp, buf); -    } +	pim_ifp = ifp->info; +	oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index); +	if (!oil->installed) +		pim_mroute_add(oil, __PRETTY_FUNCTION__); +	if (pim_if_connected_to_source(ifp, sg.src)) { +		up = pim_upstream_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, +				      __PRETTY_FUNCTION__); +		if (!up) { +			if (PIM_DEBUG_MROUTE) +				zlog_debug( +					"%s: WRONGVIF%s unable to create upstream on interface", +					pim_str_sg_dump(&sg), ifp->name); +			return -2; +		} +		PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); +		pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); +		up->channel_oil = oil; +		up->channel_oil->cc.pktcnt++; +		pim_register_join(up); +		pim_upstream_inherited_olist(up); + +		// Send the packet to the RP +		pim_mroute_msg_wholepkt(fd, ifp, buf); +	} -  return 0; +	return 0;  }  int pim_mroute_msg(int fd, const char *buf, int buf_size)  { -  struct interface     *ifp; -  struct pim_interface *pim_ifp; -  const struct ip      *ip_hdr; -  const struct igmpmsg *msg; -  char ip_src_str[INET_ADDRSTRLEN] = ""; -  char ip_dst_str[INET_ADDRSTRLEN] = ""; -  char src_str[INET_ADDRSTRLEN] = "<src?>"; -  char grp_str[INET_ADDRSTRLEN] = "<grp?>"; -  struct in_addr ifaddr; -  struct igmp_sock *igmp; - -  ip_hdr = (const struct ip *) buf; - -  if (ip_hdr->ip_p == IPPROTO_IGMP) { - -    /* We have the IP packet but we do not know which interface this packet was -     * received on. Find the interface that is on the same subnet as the source -     * of the IP packet. -     */ -    ifp = pim_if_lookup_address_vrf (ip_hdr->ip_src, VRF_DEFAULT); - -    if (!ifp) { -      if (PIM_DEBUG_MROUTE_DETAIL) { -        pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); -        pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - -        zlog_warn("%s: igmp kernel upcall could not find usable interface for %s -> %s", -                __PRETTY_FUNCTION__, -                ip_src_str, -                ip_dst_str); -      } -      return 0; -    } -    pim_ifp = ifp->info; -    ifaddr = pim_find_primary_addr(ifp); -    igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); - -    if (PIM_DEBUG_MROUTE) { -      pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); -      pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - -      zlog_warn("%s: igmp kernel upcall on %s(%p) for %s -> %s", -                __PRETTY_FUNCTION__, ifp->name, igmp, ip_src_str, ip_dst_str); -    } -    if (igmp) -      pim_igmp_packet(igmp, (char *)buf, buf_size); - -  } else if (ip_hdr->ip_p) { -    if (PIM_DEBUG_MROUTE_DETAIL) { -      pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str)); -      pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); -      zlog_debug("%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", -                 __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size); -    } - -  } else { -    msg = (const struct igmpmsg *) buf; - -    ifp = pim_if_find_by_vif_index(msg->im_vif); - -    if (!ifp) -      return 0; -    if (PIM_DEBUG_MROUTE) { -      pim_inet4_dump("<src?>", msg->im_src, src_str, sizeof(src_str)); -      pim_inet4_dump("<grp?>", msg->im_dst, grp_str, sizeof(grp_str)); -      zlog_warn("%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d  size=%d", -                __PRETTY_FUNCTION__, -                igmpmsgtype2str[msg->im_msgtype], -                msg->im_msgtype, -                ip_hdr->ip_p, -                fd, -                src_str, -                grp_str, -                ifp->name, -                msg->im_vif, buf_size); -    } - -    switch (msg->im_msgtype) { -    case IGMPMSG_WRONGVIF: -      return pim_mroute_msg_wrongvif(fd, ifp, msg); -      break; -    case IGMPMSG_NOCACHE: -      return pim_mroute_msg_nocache(fd, ifp, msg); -      break; -    case IGMPMSG_WHOLEPKT: -      return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); -      break; -    case IGMPMSG_WRVIFWHOLE: -      return pim_mroute_msg_wrvifwhole (fd, ifp, (const char *)msg); -      break; -    default: -      break; -    } -  } +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	const struct ip *ip_hdr; +	const struct igmpmsg *msg; +	char ip_src_str[INET_ADDRSTRLEN] = ""; +	char ip_dst_str[INET_ADDRSTRLEN] = ""; +	char src_str[INET_ADDRSTRLEN] = "<src?>"; +	char grp_str[INET_ADDRSTRLEN] = "<grp?>"; +	struct in_addr ifaddr; +	struct igmp_sock *igmp; + +	ip_hdr = (const struct ip *)buf; + +	if (ip_hdr->ip_p == IPPROTO_IGMP) { + +		/* We have the IP packet but we do not know which interface this +		 * packet was +		 * received on. Find the interface that is on the same subnet as +		 * the source +		 * of the IP packet. +		 */ +		ifp = pim_if_lookup_address_vrf(ip_hdr->ip_src, VRF_DEFAULT); + +		if (!ifp) { +			if (PIM_DEBUG_MROUTE_DETAIL) { +				pim_inet4_dump("<src?>", ip_hdr->ip_src, +					       ip_src_str, sizeof(ip_src_str)); +				pim_inet4_dump("<dst?>", ip_hdr->ip_dst, +					       ip_dst_str, sizeof(ip_dst_str)); + +				zlog_warn( +					"%s: igmp kernel upcall could not find usable interface for %s -> %s", +					__PRETTY_FUNCTION__, ip_src_str, +					ip_dst_str); +			} +			return 0; +		} +		pim_ifp = ifp->info; +		ifaddr = pim_find_primary_addr(ifp); +		igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, +						   ifaddr); + +		if (PIM_DEBUG_MROUTE) { +			pim_inet4_dump("<src?>", ip_hdr->ip_src, ip_src_str, +				       sizeof(ip_src_str)); +			pim_inet4_dump("<dst?>", ip_hdr->ip_dst, ip_dst_str, +				       sizeof(ip_dst_str)); + +			zlog_warn( +				"%s: igmp kernel upcall on %s(%p) for %s -> %s", +				__PRETTY_FUNCTION__, ifp->name, igmp, +				ip_src_str, ip_dst_str); +		} +		if (igmp) +			pim_igmp_packet(igmp, (char *)buf, buf_size); + +	} else if (ip_hdr->ip_p) { +		if (PIM_DEBUG_MROUTE_DETAIL) { +			pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, +				       sizeof(src_str)); +			pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, +				       sizeof(grp_str)); +			zlog_debug( +				"%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", +				__PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, +				grp_str, buf_size); +		} + +	} else { +		msg = (const struct igmpmsg *)buf; + +		ifp = pim_if_find_by_vif_index(msg->im_vif); + +		if (!ifp) +			return 0; +		if (PIM_DEBUG_MROUTE) { +			pim_inet4_dump("<src?>", msg->im_src, src_str, +				       sizeof(src_str)); +			pim_inet4_dump("<grp?>", msg->im_dst, grp_str, +				       sizeof(grp_str)); +			zlog_warn( +				"%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d  size=%d", +				__PRETTY_FUNCTION__, +				igmpmsgtype2str[msg->im_msgtype], +				msg->im_msgtype, ip_hdr->ip_p, fd, src_str, +				grp_str, ifp->name, msg->im_vif, buf_size); +		} + +		switch (msg->im_msgtype) { +		case IGMPMSG_WRONGVIF: +			return pim_mroute_msg_wrongvif(fd, ifp, msg); +			break; +		case IGMPMSG_NOCACHE: +			return pim_mroute_msg_nocache(fd, ifp, msg); +			break; +		case IGMPMSG_WHOLEPKT: +			return pim_mroute_msg_wholepkt(fd, ifp, +						       (const char *)msg); +			break; +		case IGMPMSG_WRVIFWHOLE: +			return pim_mroute_msg_wrvifwhole(fd, ifp, +							 (const char *)msg); +			break; +		default: +			break; +		} +	} -  return 0; +	return 0;  }  static int mroute_read(struct thread *t)  { -  static long long count; -  char buf[10000]; -  int result = 0; -  int cont = 1; -  int fd; -  int rd; - -  fd = THREAD_FD(t); - -  while (cont) -    { -      rd = read(fd, buf, sizeof(buf)); -      if (rd < 0) { -	if (errno == EINTR) -	  continue; -	if (errno == EWOULDBLOCK || errno == EAGAIN) -          break; - -	if (PIM_DEBUG_MROUTE) -	  zlog_warn("%s: failure reading fd=%d: errno=%d: %s", -		    __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); -	goto done; -      } - -      result = pim_mroute_msg(fd, buf, rd); - -      count++; -      if (count % qpim_packet_process == 0) -	cont = 0; -    } -  /* Keep reading */ - done: -  mroute_read_on(); +	static long long count; +	char buf[10000]; +	int result = 0; +	int cont = 1; +	int fd; +	int rd; + +	fd = THREAD_FD(t); + +	while (cont) { +		rd = read(fd, buf, sizeof(buf)); +		if (rd < 0) { +			if (errno == EINTR) +				continue; +			if (errno == EWOULDBLOCK || errno == EAGAIN) +				break; + +			if (PIM_DEBUG_MROUTE) +				zlog_warn( +					"%s: failure reading fd=%d: errno=%d: %s", +					__PRETTY_FUNCTION__, fd, errno, +					safe_strerror(errno)); +			goto done; +		} + +		result = pim_mroute_msg(fd, buf, rd); + +		count++; +		if (count % qpim_packet_process == 0) +			cont = 0; +	} +/* Keep reading */ +done: +	mroute_read_on(); -  return result; +	return result;  }  static void mroute_read_on()  { -  thread_add_read(master, mroute_read, 0, qpim_mroute_socket_fd, -                  &qpim_mroute_socket_reader); +	thread_add_read(master, mroute_read, 0, qpim_mroute_socket_fd, +			&qpim_mroute_socket_reader);  }  static void mroute_read_off()  { -  THREAD_OFF(qpim_mroute_socket_reader); +	THREAD_OFF(qpim_mroute_socket_reader);  }  int pim_mroute_socket_enable()  { -  int fd; +	int fd; -  if ( pimd_privs.change (ZPRIVS_RAISE) ) -    zlog_err ("pim_mroute_socket_enable: could not raise privs, %s", -              safe_strerror (errno) ); +	if (pimd_privs.change(ZPRIVS_RAISE)) +		zlog_err("pim_mroute_socket_enable: could not raise privs, %s", +			 safe_strerror(errno)); -  fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); +	fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); -  if ( pimd_privs.change (ZPRIVS_LOWER) ) -    zlog_err ("pim_mroute_socket_enable: could not lower privs, %s", -	      safe_strerror (errno) ); +	if (pimd_privs.change(ZPRIVS_LOWER)) +		zlog_err("pim_mroute_socket_enable: could not lower privs, %s", +			 safe_strerror(errno)); -  if (fd < 0) { -    zlog_warn("Could not create mroute socket: errno=%d: %s", -	      errno, safe_strerror(errno)); -    return -2; -  } +	if (fd < 0) { +		zlog_warn("Could not create mroute socket: errno=%d: %s", errno, +			  safe_strerror(errno)); +		return -2; +	} -  if (pim_mroute_set(fd, 1)) { -    zlog_warn("Could not enable mroute on socket fd=%d: errno=%d: %s", -	      fd, errno, safe_strerror(errno)); -    close(fd); -    return -3; -  } +	if (pim_mroute_set(fd, 1)) { +		zlog_warn( +			"Could not enable mroute on socket fd=%d: errno=%d: %s", +			fd, errno, safe_strerror(errno)); +		close(fd); +		return -3; +	} -  qpim_mroute_socket_fd       = fd; +	qpim_mroute_socket_fd = fd; -  qpim_mroute_socket_creation = pim_time_monotonic_sec(); -  mroute_read_on(); +	qpim_mroute_socket_creation = pim_time_monotonic_sec(); +	mroute_read_on(); -  return 0; +	return 0;  }  int pim_mroute_socket_disable()  { -  if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { -    zlog_warn("Could not disable mroute on socket fd=%d: errno=%d: %s", -	      qpim_mroute_socket_fd, errno, safe_strerror(errno)); -    return -2; -  } - -  if (close(qpim_mroute_socket_fd)) { -    zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", -	      qpim_mroute_socket_fd, errno, safe_strerror(errno)); -    return -3; -  } - -  mroute_read_off(); -  qpim_mroute_socket_fd = -1; - -  return 0; +	if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { +		zlog_warn( +			"Could not disable mroute on socket fd=%d: errno=%d: %s", +			qpim_mroute_socket_fd, errno, safe_strerror(errno)); +		return -2; +	} + +	if (close(qpim_mroute_socket_fd)) { +		zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", +			  qpim_mroute_socket_fd, errno, safe_strerror(errno)); +		return -3; +	} + +	mroute_read_off(); +	qpim_mroute_socket_fd = -1; + +	return 0;  }  /* @@ -701,249 +726,248 @@ int pim_mroute_socket_disable()    would be used for multicast forwarding, a corresponding multicast    interface must be added to the kernel.   */ -int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags) +int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, +		       unsigned char flags)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct vifctl vc; -  int err; +	struct pim_interface *pim_ifp = ifp->info; +	struct vifctl vc; +	int err; -  memset(&vc, 0, sizeof(vc)); -  vc.vifc_vifi = pim_ifp->mroute_vif_index; +	memset(&vc, 0, sizeof(vc)); +	vc.vifc_vifi = pim_ifp->mroute_vif_index;  #ifdef VIFF_USE_IFINDEX -  vc.vifc_lcl_ifindex = ifp->ifindex; +	vc.vifc_lcl_ifindex = ifp->ifindex;  #else -  if (ifaddr.s_addr == INADDR_ANY) { -    zlog_warn("%s: unnumbered interfaces are not supported on this platform", -	      __PRETTY_FUNCTION__); -    return -1; -  } -  memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); +	if (ifaddr.s_addr == INADDR_ANY) { +		zlog_warn( +			"%s: unnumbered interfaces are not supported on this platform", +			__PRETTY_FUNCTION__); +		return -1; +	} +	memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr));  #endif -  vc.vifc_flags = flags; -  vc.vifc_threshold = PIM_MROUTE_MIN_TTL; -  vc.vifc_rate_limit = 0; - -#ifdef PIM_DVMRP_TUNNEL   -  if (vc.vifc_flags & VIFF_TUNNEL) { -    memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, sizeof(vc.vifc_rmt_addr)); -  } +	vc.vifc_flags = flags; +	vc.vifc_threshold = PIM_MROUTE_MIN_TTL; +	vc.vifc_rate_limit = 0; + +#ifdef PIM_DVMRP_TUNNEL +	if (vc.vifc_flags & VIFF_TUNNEL) { +		memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, +		       sizeof(vc.vifc_rmt_addr)); +	}  #endif -  err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, (void*) &vc, sizeof(vc)); -  if (err) { -    char ifaddr_str[INET_ADDRSTRLEN]; +	err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, +			 (void *)&vc, sizeof(vc)); +	if (err) { +		char ifaddr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<ifaddr?>", ifaddr, ifaddr_str, sizeof(ifaddr_str)); +		pim_inet4_dump("<ifaddr?>", ifaddr, ifaddr_str, +			       sizeof(ifaddr_str)); -    zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", -	      __FILE__, __PRETTY_FUNCTION__, -	      qpim_mroute_socket_fd, ifp->ifindex, ifaddr_str, flags, -	      errno, safe_strerror(errno)); -    return -2; -  } +		zlog_warn( +			"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", +			__FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, +			ifp->ifindex, ifaddr_str, flags, errno, +			safe_strerror(errno)); +		return -2; +	} -  return 0; +	return 0;  }  int pim_mroute_del_vif(int vif_index)  { -  struct vifctl vc; -  int err; - -  if (PIM_DEBUG_MROUTE) -    { -      struct interface *ifp = pim_if_find_by_vif_index (vif_index); -      zlog_debug ("%s %s: Del Vif %d (%s) ", __FILE__, -                  __PRETTY_FUNCTION__, vif_index, ifp ? ifp->name : "NULL"); -    } - -  memset(&vc, 0, sizeof(vc)); -  vc.vifc_vifi = vif_index; +	struct vifctl vc; +	int err; + +	if (PIM_DEBUG_MROUTE) { +		struct interface *ifp = pim_if_find_by_vif_index(vif_index); +		zlog_debug("%s %s: Del Vif %d (%s) ", __FILE__, +			   __PRETTY_FUNCTION__, vif_index, +			   ifp ? ifp->name : "NULL"); +	} -  err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, (void*) &vc, sizeof(vc));  -  if (err) { -    zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", -	      __FILE__, __PRETTY_FUNCTION__, -	      qpim_mroute_socket_fd, vif_index, -	      errno, safe_strerror(errno)); -    return -2; -  } +	memset(&vc, 0, sizeof(vc)); +	vc.vifc_vifi = vif_index; + +	err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, +			 (void *)&vc, sizeof(vc)); +	if (err) { +		zlog_warn( +			"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", +			__FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, +			vif_index, errno, safe_strerror(errno)); +		return -2; +	} -  return 0; +	return 0;  }  int pim_mroute_add(struct channel_oil *c_oil, const char *name)  { -  int err; -  int orig = 0; -  int orig_iif_vif = 0; - -  qpim_mroute_add_last = pim_time_monotonic_sec(); -  ++qpim_mroute_add_events; - -  /* Do not install route if incoming interface is undefined. */ -  if (c_oil->oil.mfcc_parent >= MAXVIFS) -    { -      if (PIM_DEBUG_MROUTE) -        { -          char buf[1000]; -          zlog_debug("%s(%s) %s Attempting to add vifi that is invalid to mroute table", -              __PRETTY_FUNCTION__, name, pim_channel_oil_dump (c_oil, buf, sizeof(buf))); -        } -      return -2; -    } - -  /* The linux kernel *expects* the incoming -   * vif to be part of the outgoing list -   * in the case of a (*,G). -   */ -  if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) -    { -      orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; -      c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; -    } +	int err; +	int orig = 0; +	int orig_iif_vif = 0; + +	qpim_mroute_add_last = pim_time_monotonic_sec(); +	++qpim_mroute_add_events; + +	/* Do not install route if incoming interface is undefined. */ +	if (c_oil->oil.mfcc_parent >= MAXVIFS) { +		if (PIM_DEBUG_MROUTE) { +			char buf[1000]; +			zlog_debug( +				"%s(%s) %s Attempting to add vifi that is invalid to mroute table", +				__PRETTY_FUNCTION__, name, +				pim_channel_oil_dump(c_oil, buf, sizeof(buf))); +		} +		return -2; +	} -  /* -   * If we have an unresolved cache entry for the S,G -   * it is owned by the pimreg for the incoming IIF -   * So set pimreg as the IIF temporarily to cause -   * the packets to be forwarded.  Then set it -   * to the correct IIF afterwords. -   */ -  if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && -      c_oil->oil.mfcc_parent != 0) -    { -      orig_iif_vif = c_oil->oil.mfcc_parent; -      c_oil->oil.mfcc_parent = 0; -    } -  err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, -		   &c_oil->oil, sizeof(c_oil->oil)); +	/* The linux kernel *expects* the incoming +	 * vif to be part of the outgoing list +	 * in the case of a (*,G). +	 */ +	if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) { +		orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; +		c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; +	} -  if (!err && !c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && -      orig_iif_vif != 0) -    { -      c_oil->oil.mfcc_parent = orig_iif_vif; -      err = setsockopt (qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, -			&c_oil->oil, sizeof (c_oil->oil)); -    } +	/* +	 * If we have an unresolved cache entry for the S,G +	 * it is owned by the pimreg for the incoming IIF +	 * So set pimreg as the IIF temporarily to cause +	 * the packets to be forwarded.  Then set it +	 * to the correct IIF afterwords. +	 */ +	if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY +	    && c_oil->oil.mfcc_parent != 0) { +		orig_iif_vif = c_oil->oil.mfcc_parent; +		c_oil->oil.mfcc_parent = 0; +	} +	err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, +			 &c_oil->oil, sizeof(c_oil->oil)); + +	if (!err && !c_oil->installed +	    && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY +	    && orig_iif_vif != 0) { +		c_oil->oil.mfcc_parent = orig_iif_vif; +		err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, +				 &c_oil->oil, sizeof(c_oil->oil)); +	} -  if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) -      c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; +	if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) +		c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; -  if (err) { -    zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", -	      __FILE__, __PRETTY_FUNCTION__, -	      qpim_mroute_socket_fd, -	      errno, safe_strerror(errno)); -    return -2; -  } +	if (err) { +		zlog_warn( +			"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", +			__FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, +			errno, safe_strerror(errno)); +		return -2; +	} -  if (PIM_DEBUG_MROUTE) -    { -      char buf[1000]; -      zlog_debug("%s(%s), Added Route: %s", -                 __PRETTY_FUNCTION__, name, -                 pim_channel_oil_dump (c_oil, buf, sizeof(buf))); -    } +	if (PIM_DEBUG_MROUTE) { +		char buf[1000]; +		zlog_debug("%s(%s), Added Route: %s", __PRETTY_FUNCTION__, name, +			   pim_channel_oil_dump(c_oil, buf, sizeof(buf))); +	} -  c_oil->installed = 1; -  return 0; +	c_oil->installed = 1; +	return 0;  } -int pim_mroute_del (struct channel_oil *c_oil, const char *name) +int pim_mroute_del(struct channel_oil *c_oil, const char *name)  { -  int err; - -  qpim_mroute_del_last = pim_time_monotonic_sec(); -  ++qpim_mroute_del_events; +	int err; + +	qpim_mroute_del_last = pim_time_monotonic_sec(); +	++qpim_mroute_del_events; + +	if (!c_oil->installed) { +		if (PIM_DEBUG_MROUTE) { +			char buf[1000]; +			zlog_debug( +				"%s %s: vifi %d for route is %s not installed, do not need to send del req. ", +				__FILE__, __PRETTY_FUNCTION__, +				c_oil->oil.mfcc_parent, +				pim_channel_oil_dump(c_oil, buf, sizeof(buf))); +		} +		return -2; +	} -  if (!c_oil->installed) -    { -      if (PIM_DEBUG_MROUTE) -        { -          char buf[1000]; -          zlog_debug("%s %s: vifi %d for route is %s not installed, do not need to send del req. ", -                __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, -                pim_channel_oil_dump (c_oil, buf, sizeof(buf))); -        } -      return -2; -    } +	err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, +			 &c_oil->oil, sizeof(c_oil->oil)); +	if (err) { +		if (PIM_DEBUG_MROUTE) +			zlog_warn( +				"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", +				__FILE__, __PRETTY_FUNCTION__, +				qpim_mroute_socket_fd, errno, +				safe_strerror(errno)); +		return -2; +	} -  err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil)); -  if (err) { -    if (PIM_DEBUG_MROUTE) -      zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", -		__FILE__, __PRETTY_FUNCTION__, -		qpim_mroute_socket_fd, -		errno, safe_strerror(errno)); -    return -2; -  } - -  if (PIM_DEBUG_MROUTE) -    { -      char buf[1000]; -      zlog_debug("%s(%s), Deleted Route: %s", -                 __PRETTY_FUNCTION__, name, -                 pim_channel_oil_dump (c_oil, buf, sizeof(buf))); -    } +	if (PIM_DEBUG_MROUTE) { +		char buf[1000]; +		zlog_debug("%s(%s), Deleted Route: %s", __PRETTY_FUNCTION__, +			   name, pim_channel_oil_dump(c_oil, buf, sizeof(buf))); +	} -  //Reset kernel installed flag -  c_oil->installed = 0; +	// Reset kernel installed flag +	c_oil->installed = 0; -  return 0; +	return 0;  } -void -pim_mroute_update_counters (struct channel_oil *c_oil) +void pim_mroute_update_counters(struct channel_oil *c_oil)  { -  struct sioc_sg_req sgreq; - -  c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; -  c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; -  c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; - -  if (!c_oil->installed) -    { -      c_oil->cc.lastused = 100 * qpim_keep_alive_time; -      if (PIM_DEBUG_MROUTE) -	{ -	  struct prefix_sg sg; - -	  sg.src = c_oil->oil.mfcc_origin; -	  sg.grp = c_oil->oil.mfcc_mcastgrp; -	  if (PIM_DEBUG_MROUTE) -	    zlog_debug("Channel(%s) is not installed no need to collect data from kernel", -		       pim_str_sg_dump (&sg)); +	struct sioc_sg_req sgreq; + +	c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; +	c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; +	c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; + +	if (!c_oil->installed) { +		c_oil->cc.lastused = 100 * qpim_keep_alive_time; +		if (PIM_DEBUG_MROUTE) { +			struct prefix_sg sg; + +			sg.src = c_oil->oil.mfcc_origin; +			sg.grp = c_oil->oil.mfcc_mcastgrp; +			if (PIM_DEBUG_MROUTE) +				zlog_debug( +					"Channel(%s) is not installed no need to collect data from kernel", +					pim_str_sg_dump(&sg)); +		} +		return;  	} -      return; -    } - -  memset (&sgreq, 0, sizeof(sgreq)); -  sgreq.src = c_oil->oil.mfcc_origin; -  sgreq.grp = c_oil->oil.mfcc_mcastgrp; - -  pim_zlookup_sg_statistics (c_oil); -  if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) -    { -      if (PIM_DEBUG_MROUTE) -	{ -	  struct prefix_sg sg; -	  sg.src = c_oil->oil.mfcc_origin; -	  sg.grp = c_oil->oil.mfcc_mcastgrp; - -	  zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", -		     (unsigned long)SIOCGETSGCNT, -		     pim_str_sg_dump (&sg), -		     errno, -		     safe_strerror(errno)); +	memset(&sgreq, 0, sizeof(sgreq)); +	sgreq.src = c_oil->oil.mfcc_origin; +	sgreq.grp = c_oil->oil.mfcc_mcastgrp; + +	pim_zlookup_sg_statistics(c_oil); +	if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { +		if (PIM_DEBUG_MROUTE) { +			struct prefix_sg sg; + +			sg.src = c_oil->oil.mfcc_origin; +			sg.grp = c_oil->oil.mfcc_mcastgrp; + +			zlog_warn( +				"ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", +				(unsigned long)SIOCGETSGCNT, +				pim_str_sg_dump(&sg), errno, +				safe_strerror(errno)); +		} +		return;  	} -      return; -    } -  c_oil->cc.pktcnt = sgreq.pktcnt; -  c_oil->cc.bytecnt = sgreq.bytecnt; -  c_oil->cc.wrong_if = sgreq.wrong_if; +	c_oil->cc.pktcnt = sgreq.pktcnt; +	c_oil->cc.bytecnt = sgreq.bytecnt; +	c_oil->cc.wrong_if = sgreq.wrong_if; -  return; +	return;  } diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index 36dce8e610..eb6c40b676 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -73,25 +73,25 @@ typedef unsigned short vifi_t;  #ifndef HAVE_STRUCT_VIFCTL  struct vifctl { -	vifi_t	vifc_vifi;		/* Index of VIF */ -	unsigned char vifc_flags;	/* VIFF_ flags */ -	unsigned char vifc_threshold;	/* ttl limit */ -	unsigned int vifc_rate_limit;	/* Rate limiter values (NI) */ -	struct in_addr vifc_lcl_addr;	/* Our address */ -	struct in_addr vifc_rmt_addr;	/* IPIP tunnel addr */ +	vifi_t vifc_vifi;	     /* Index of VIF */ +	unsigned char vifc_flags;     /* VIFF_ flags */ +	unsigned char vifc_threshold; /* ttl limit */ +	unsigned int vifc_rate_limit; /* Rate limiter values (NI) */ +	struct in_addr vifc_lcl_addr; /* Our address */ +	struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */  };  #endif  #ifndef HAVE_STRUCT_MFCCTL  struct mfcctl { -  struct in_addr mfcc_origin;             /* Origin of mcast      */ -  struct in_addr mfcc_mcastgrp;           /* Group in question    */ -  vifi_t         mfcc_parent;             /* Where it arrived     */ -  unsigned char  mfcc_ttls[MAXVIFS];      /* Where it is going    */ -  unsigned int   mfcc_pkt_cnt;            /* pkt count for src-grp */ -  unsigned int   mfcc_byte_cnt; -  unsigned int   mfcc_wrong_if; -  int            mfcc_expire; +	struct in_addr mfcc_origin;       /* Origin of mcast      */ +	struct in_addr mfcc_mcastgrp;     /* Group in question    */ +	vifi_t mfcc_parent;		  /* Where it arrived     */ +	unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going    */ +	unsigned int mfcc_pkt_cnt;	/* pkt count for src-grp */ +	unsigned int mfcc_byte_cnt; +	unsigned int mfcc_wrong_if; +	int mfcc_expire;  };  #endif @@ -107,11 +107,11 @@ struct mfcctl {   */  #ifndef HAVE_STRUCT_SIOC_SG_REQ  struct sioc_sg_req { -  struct in_addr src; -  struct in_addr grp; -  unsigned long pktcnt; -  unsigned long bytecnt; -  unsigned long wrong_if; +	struct in_addr src; +	struct in_addr grp; +	unsigned long pktcnt; +	unsigned long bytecnt; +	unsigned long wrong_if;  };  #endif @@ -126,11 +126,11 @@ struct sioc_sg_req {   */  #ifndef HAVE_STRUCT_SIOC_VIF_REQ  struct sioc_vif_req { -  vifi_t  vifi;           /* Which iface */ -  unsigned long icount;   /* In packets */ -  unsigned long ocount;   /* Out packets */ -  unsigned long ibytes;   /* In bytes */ -  unsigned long obytes;   /* Out bytes */ +	vifi_t vifi;	  /* Which iface */ +	unsigned long icount; /* In packets */ +	unsigned long ocount; /* Out packets */ +	unsigned long ibytes; /* In bytes */ +	unsigned long obytes; /* Out bytes */  };  #endif @@ -144,14 +144,13 @@ struct sioc_vif_req {  #endif  #ifndef HAVE_STRUCT_IGMPMSG -struct igmpmsg -{ -  uint32_t unused1,unused2; -  unsigned char im_msgtype;               /* What is this */ -  unsigned char im_mbz;                   /* Must be zero */ -  unsigned char im_vif;                   /* Interface (this ought to be a vifi_t!) */ -  unsigned char unused3; -  struct in_addr im_src,im_dst; +struct igmpmsg { +	uint32_t unused1, unused2; +	unsigned char im_msgtype; /* What is this */ +	unsigned char im_mbz;     /* Must be zero */ +	unsigned char im_vif;     /* Interface (this ought to be a vifi_t!) */ +	unsigned char unused3; +	struct in_addr im_src, im_dst;  };  #endif  #endif @@ -167,7 +166,8 @@ struct igmpmsg  int pim_mroute_socket_enable(void);  int pim_mroute_socket_disable(void); -int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags); +int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, +		       unsigned char flags);  int pim_mroute_del_vif(int vif_index);  int pim_mroute_add(struct channel_oil *c_oil, const char *name); @@ -175,5 +175,5 @@ int pim_mroute_del(struct channel_oil *c_oil, const char *name);  int pim_mroute_msg(int fd, const char *buf, int buf_size); -void pim_mroute_update_counters (struct channel_oil *c_oil); +void pim_mroute_update_counters(struct channel_oil *c_oil);  #endif /* PIM_MROUTE_H */ diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 170692e7f0..0f653e70a4 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -47,119 +47,119 @@ struct pim_msdp pim_msdp, *msdp = &pim_msdp;  static void pim_msdp_peer_listen(struct pim_msdp_peer *mp);  static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start);  static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start); -static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start); +static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, +					   bool start);  static void pim_msdp_peer_free(struct pim_msdp_peer *mp);  static void pim_msdp_enable(void);  static void pim_msdp_sa_adv_timer_setup(bool start); -static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags); +static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, +			      enum pim_msdp_sa_flags flags);  static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2);  static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr); -static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr); +static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, +				   struct pim_msdp_mg_mbr *mbr);  /************************ SA cache management ******************************/ -static void -pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, const char *timer_str) +static void pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, +					 const char *timer_str)  { -  zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str); +	zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str);  }  /* RFC-3618:Sec-5.1 - global active source advertisement timer */ -static int -pim_msdp_sa_adv_timer_cb(struct thread *t) +static int pim_msdp_sa_adv_timer_cb(struct thread *t)  { -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP SA advertisment timer expired"); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP SA advertisment timer expired"); +	} -  pim_msdp_sa_adv_timer_setup(true /* start */); -  pim_msdp_pkt_sa_tx(); -  return 0; +	pim_msdp_sa_adv_timer_setup(true /* start */); +	pim_msdp_pkt_sa_tx(); +	return 0;  } -static void -pim_msdp_sa_adv_timer_setup(bool start) +static void pim_msdp_sa_adv_timer_setup(bool start)  { -  THREAD_OFF(msdp->sa_adv_timer); -  if (start) { -    thread_add_timer(msdp->master, pim_msdp_sa_adv_timer_cb, NULL, -                     PIM_MSDP_SA_ADVERTISMENT_TIME, &msdp->sa_adv_timer); -  } +	THREAD_OFF(msdp->sa_adv_timer); +	if (start) { +		thread_add_timer(msdp->master, pim_msdp_sa_adv_timer_cb, NULL, +				 PIM_MSDP_SA_ADVERTISMENT_TIME, +				 &msdp->sa_adv_timer); +	}  }  /* RFC-3618:Sec-5.3 - SA cache state timer */ -static int -pim_msdp_sa_state_timer_cb(struct thread *t) +static int pim_msdp_sa_state_timer_cb(struct thread *t)  { -  struct pim_msdp_sa *sa; +	struct pim_msdp_sa *sa; -  sa = THREAD_ARG(t); +	sa = THREAD_ARG(t); -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_sa_timer_expiry_log(sa, "state"); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_sa_timer_expiry_log(sa, "state"); +	} -  pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER); -  return 0; +	pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER); +	return 0;  } -static void -pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start) +static void pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start)  { -  THREAD_OFF(sa->sa_state_timer); -  if (start) { -    thread_add_timer(msdp->master, pim_msdp_sa_state_timer_cb, sa, -                     PIM_MSDP_SA_HOLD_TIME, &sa->sa_state_timer); -  } +	THREAD_OFF(sa->sa_state_timer); +	if (start) { +		thread_add_timer(msdp->master, pim_msdp_sa_state_timer_cb, sa, +				 PIM_MSDP_SA_HOLD_TIME, &sa->sa_state_timer); +	}  } -static void -pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) +static void pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa)  { -  struct pim_upstream *up = sa->up; -  if (!up) { -    return; -  } +	struct pim_upstream *up = sa->up; +	if (!up) { +		return; +	} -  sa->up = NULL; -  if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { -    PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); -    sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; -    pim_upstream_del(up, __PRETTY_FUNCTION__); -    sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; -  } +	sa->up = NULL; +	if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { +		PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); +		sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; +		pim_upstream_del(up, __PRETTY_FUNCTION__); +		sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; +	} -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str); +	}  } -static bool -pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up) +static bool pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, +					struct pim_upstream *xg_up)  { -  if (!(sa->flags & PIM_MSDP_SAF_PEER)) { -    /* SA should have been rxed from a peer */ -    return false; -  } -  /* check if we are RP */ -  if (!I_am_RP(sa->sg.grp)) { -    return false; -  } +	if (!(sa->flags & PIM_MSDP_SAF_PEER)) { +		/* SA should have been rxed from a peer */ +		return false; +	} +	/* check if we are RP */ +	if (!I_am_RP(sa->sg.grp)) { +		return false; +	} -  /* check if we have a (*, G) with a non-empty immediate OIL */ -  if (!xg_up) { -    struct prefix_sg sg; +	/* check if we have a (*, G) with a non-empty immediate OIL */ +	if (!xg_up) { +		struct prefix_sg sg; -    memset(&sg, 0, sizeof(sg)); -    sg.grp = sa->sg.grp; +		memset(&sg, 0, sizeof(sg)); +		sg.grp = sa->sg.grp; -    xg_up = pim_upstream_find(&sg); -  } -  if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) { -    /* join desired will be true for such (*, G) entries so we will -     * just look at join_state and let the PIM state machine do the rest of -     * the magic */ -    return false; -  } +		xg_up = pim_upstream_find(&sg); +	} +	if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) { +		/* join desired will be true for such (*, G) entries so we will +		 * just look at join_state and let the PIM state machine do the +		 * rest of +		 * the magic */ +		return false; +	} -  return true; +	return true;  }  /* Upstream add evaluation needs to happen everytime - @@ -170,164 +170,164 @@ pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up)   *    (considering #4); but just in case an entry gets nuked without   *    upstream state transition   *    */ -static void -pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, -                            struct pim_upstream *xg_up, const char *ctx) -{ -  struct pim_upstream *up; - -  if (!pim_msdp_sa_upstream_add_ok(sa, xg_up)) { -    pim_msdp_sa_upstream_del(sa); -    return; -  } - -  if (sa->up) { -    /* nothing to do */ -    return; -  } - -  up = pim_upstream_find(&sa->sg); -  if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) { -    /* somehow we lost track of the upstream ptr? best log it */ -    sa->up = up; -    if (PIM_DEBUG_MSDP_EVENTS) { -      zlog_debug("MSDP SA %s SPT reference missing", sa->sg_str); -    } -    return; -  } - -  /* RFC3618: "RP triggers a (S, G) join event towards the data source -   * as if a JP message was rxed addressed to the RP itself." */ -  up = pim_upstream_add(&sa->sg, NULL /* iif */, -                        PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, -                        __PRETTY_FUNCTION__); - -  sa->up = up; -  if (up) { -    /* update inherited oil */ -    pim_upstream_inherited_olist(up); -    /* should we also start the kat in parallel? we will need it when the -     * SA ages out */ -    if (PIM_DEBUG_MSDP_EVENTS) { -      zlog_debug("MSDP SA %s referenced SPT", sa->sg_str); -    } -  } else { -    if (PIM_DEBUG_MSDP_EVENTS) { -      zlog_debug("MSDP SA %s SPT reference failed", sa->sg_str); -    } -  } +static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, +					struct pim_upstream *xg_up, +					const char *ctx) +{ +	struct pim_upstream *up; + +	if (!pim_msdp_sa_upstream_add_ok(sa, xg_up)) { +		pim_msdp_sa_upstream_del(sa); +		return; +	} + +	if (sa->up) { +		/* nothing to do */ +		return; +	} + +	up = pim_upstream_find(&sa->sg); +	if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) { +		/* somehow we lost track of the upstream ptr? best log it */ +		sa->up = up; +		if (PIM_DEBUG_MSDP_EVENTS) { +			zlog_debug("MSDP SA %s SPT reference missing", +				   sa->sg_str); +		} +		return; +	} + +	/* RFC3618: "RP triggers a (S, G) join event towards the data source +	 * as if a JP message was rxed addressed to the RP itself." */ +	up = pim_upstream_add(&sa->sg, NULL /* iif */, +			      PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, +			      __PRETTY_FUNCTION__); + +	sa->up = up; +	if (up) { +		/* update inherited oil */ +		pim_upstream_inherited_olist(up); +		/* should we also start the kat in parallel? we will need it +		 * when the +		 * SA ages out */ +		if (PIM_DEBUG_MSDP_EVENTS) { +			zlog_debug("MSDP SA %s referenced SPT", sa->sg_str); +		} +	} else { +		if (PIM_DEBUG_MSDP_EVENTS) { +			zlog_debug("MSDP SA %s SPT reference failed", +				   sa->sg_str); +		} +	}  }  /* release all mem associated with a sa */ -static void -pim_msdp_sa_free(struct pim_msdp_sa *sa) +static void pim_msdp_sa_free(struct pim_msdp_sa *sa)  { -  XFREE(MTYPE_PIM_MSDP_SA, sa); +	XFREE(MTYPE_PIM_MSDP_SA, sa);  } -static struct pim_msdp_sa * -pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) +static struct pim_msdp_sa *pim_msdp_sa_new(struct prefix_sg *sg, +					   struct in_addr rp)  { -  struct pim_msdp_sa *sa; +	struct pim_msdp_sa *sa; -  sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); -  if (!sa) { -    zlog_err("%s: PIM XCALLOC(%zu) failure", -	     __PRETTY_FUNCTION__, sizeof(*sa)); -    return NULL; -  } +	sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); +	if (!sa) { +		zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, +			 sizeof(*sa)); +		return NULL; +	} -  sa->sg = *sg; -  pim_str_sg_set(sg, sa->sg_str); -  sa->rp = rp; -  sa->uptime = pim_time_monotonic_sec(); +	sa->sg = *sg; +	pim_str_sg_set(sg, sa->sg_str); +	sa->rp = rp; +	sa->uptime = pim_time_monotonic_sec(); -  /* insert into misc tables for easy access */ -  sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern); -  if (!sa) { -    zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); -    pim_msdp_sa_free(sa); -    return NULL; -  } -  listnode_add_sort(msdp->sa_list, sa); +	/* insert into misc tables for easy access */ +	sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern); +	if (!sa) { +		zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); +		pim_msdp_sa_free(sa); +		return NULL; +	} +	listnode_add_sort(msdp->sa_list, sa); -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP SA %s created", sa->sg_str); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP SA %s created", sa->sg_str); +	} -  return sa; +	return sa;  } -static struct pim_msdp_sa * -pim_msdp_sa_find(struct prefix_sg *sg) +static struct pim_msdp_sa *pim_msdp_sa_find(struct prefix_sg *sg)  { -  struct pim_msdp_sa lookup; +	struct pim_msdp_sa lookup; -  lookup.sg = *sg; -  return hash_lookup(msdp->sa_hash, &lookup); +	lookup.sg = *sg; +	return hash_lookup(msdp->sa_hash, &lookup);  } -static struct pim_msdp_sa * -pim_msdp_sa_add(struct prefix_sg *sg, struct in_addr rp) +static struct pim_msdp_sa *pim_msdp_sa_add(struct prefix_sg *sg, +					   struct in_addr rp)  { -  struct pim_msdp_sa *sa; +	struct pim_msdp_sa *sa; -  sa = pim_msdp_sa_find(sg); -  if (sa) { -    return sa; -  } +	sa = pim_msdp_sa_find(sg); +	if (sa) { +		return sa; +	} -  return pim_msdp_sa_new(sg, rp); +	return pim_msdp_sa_new(sg, rp);  } -static void -pim_msdp_sa_del(struct pim_msdp_sa * sa) +static void pim_msdp_sa_del(struct pim_msdp_sa *sa)  { -  /* this is somewhat redundant - still want to be careful not to leave -   * stale upstream references */ -  pim_msdp_sa_upstream_del(sa); +	/* this is somewhat redundant - still want to be careful not to leave +	 * stale upstream references */ +	pim_msdp_sa_upstream_del(sa); -  /* stop timers */ -  pim_msdp_sa_state_timer_setup(sa, false /* start */); +	/* stop timers */ +	pim_msdp_sa_state_timer_setup(sa, false /* start */); -  /* remove the entry from various tables */ -  listnode_delete(msdp->sa_list, sa); -  hash_release(msdp->sa_hash, sa); +	/* remove the entry from various tables */ +	listnode_delete(msdp->sa_list, sa); +	hash_release(msdp->sa_hash, sa); -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP SA %s deleted", sa->sg_str); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP SA %s deleted", sa->sg_str); +	} -  /* free up any associated memory */ -  pim_msdp_sa_free(sa); +	/* free up any associated memory */ +	pim_msdp_sa_free(sa);  } -static void -pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct in_addr rp) +static void pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, +				    struct pim_msdp_peer *mp, struct in_addr rp)  { -  struct pim_msdp_peer *old_mp; +	struct pim_msdp_peer *old_mp; -  /* optimize the "no change" case as it will happen -   * frequently/periodically */ -  if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { -    return; -  } +	/* optimize the "no change" case as it will happen +	 * frequently/periodically */ +	if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { +		return; +	} -  /* any time the peer ip changes also update the rp address */ -  if (PIM_INADDR_ISNOT_ANY(sa->peer)) { -    old_mp = pim_msdp_peer_find(sa->peer); -    if (old_mp && old_mp->sa_cnt) { -      --old_mp->sa_cnt; -    } -  } +	/* any time the peer ip changes also update the rp address */ +	if (PIM_INADDR_ISNOT_ANY(sa->peer)) { +		old_mp = pim_msdp_peer_find(sa->peer); +		if (old_mp && old_mp->sa_cnt) { +			--old_mp->sa_cnt; +		} +	} -  if (mp) { -    ++mp->sa_cnt; -    sa->peer = mp->peer; -  } else { -    sa->peer.s_addr = PIM_NET_INADDR_ANY; -  } -  sa->rp = rp; +	if (mp) { +		++mp->sa_cnt; +		sa->peer = mp->peer; +	} else { +		sa->peer.s_addr = PIM_NET_INADDR_ANY; +	} +	sa->rp = rp;  }  /* When a local active-source is removed there is no way to withdraw the @@ -335,88 +335,93 @@ pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct   * not be sent in supsequent SA updates. Peers will consequently timeout the   * SA.   * Similarly a "peer-added" SA is never explicitly deleted. It is simply - * aged out overtime if not seen in the SA updates from the peers.  + * aged out overtime if not seen in the SA updates from the peers.   * XXX: should we provide a knob to drop entries learnt from a peer when the   * peer goes down? */ -static void -pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) -{ -  bool update_up = false; - -  if ((sa->flags &PIM_MSDP_SAF_LOCAL)) { -    if (flags & PIM_MSDP_SAF_LOCAL) { -      if (PIM_DEBUG_MSDP_EVENTS) { -        zlog_debug("MSDP SA %s local reference removed", sa->sg_str); -      } -      if (msdp->local_cnt) -        --msdp->local_cnt; -    } -  } - -  if ((sa->flags &PIM_MSDP_SAF_PEER)) { -    if (flags & PIM_MSDP_SAF_PEER) { -      struct in_addr rp; - -      if (PIM_DEBUG_MSDP_EVENTS) { -        zlog_debug("MSDP SA %s peer reference removed", sa->sg_str); -      } -      pim_msdp_sa_state_timer_setup(sa, false /* start */); -      rp.s_addr = INADDR_ANY; -      pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp); -      /* if peer ref was removed we need to remove the msdp reference on the -       * msdp entry */ -      update_up = true; -    } -  } - -  sa->flags &= ~flags; -  if (update_up) { -    pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); -  } - -  if (!(sa->flags & PIM_MSDP_SAF_REF)) { -    pim_msdp_sa_del(sa); -  } -} - -void -pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, -                struct in_addr rp) -{ -  struct pim_msdp_sa *sa; - -  sa = pim_msdp_sa_add(sg, rp); -  if (!sa) { -    return; -  } - -  /* reference it */ -  if (mp) { -    if (!(sa->flags & PIM_MSDP_SAF_PEER)) { -      sa->flags |= PIM_MSDP_SAF_PEER; -      if (PIM_DEBUG_MSDP_EVENTS) { -        zlog_debug("MSDP SA %s added by peer", sa->sg_str); -      } -    } -    pim_msdp_sa_peer_ip_set(sa, mp, rp); -    /* start/re-start the state timer to prevent cache expiry */ -    pim_msdp_sa_state_timer_setup(sa, true /* start */); -    /* We re-evaluate SA "SPT-trigger" everytime we hear abt it from a -     * peer. XXX: If this becomes too much of a periodic overhead we -     * can make it event based */ -    pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref"); -  } else { -    if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { -      sa->flags |= PIM_MSDP_SAF_LOCAL; -      ++msdp->local_cnt; -      if (PIM_DEBUG_MSDP_EVENTS) { -        zlog_debug("MSDP SA %s added locally", sa->sg_str); -      } -      /* send an immediate SA update to peers */ -      pim_msdp_pkt_sa_tx_one(sa); -    } -    sa->flags &= ~PIM_MSDP_SAF_STALE; -  } +static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, +			      enum pim_msdp_sa_flags flags) +{ +	bool update_up = false; + +	if ((sa->flags & PIM_MSDP_SAF_LOCAL)) { +		if (flags & PIM_MSDP_SAF_LOCAL) { +			if (PIM_DEBUG_MSDP_EVENTS) { +				zlog_debug("MSDP SA %s local reference removed", +					   sa->sg_str); +			} +			if (msdp->local_cnt) +				--msdp->local_cnt; +		} +	} + +	if ((sa->flags & PIM_MSDP_SAF_PEER)) { +		if (flags & PIM_MSDP_SAF_PEER) { +			struct in_addr rp; + +			if (PIM_DEBUG_MSDP_EVENTS) { +				zlog_debug("MSDP SA %s peer reference removed", +					   sa->sg_str); +			} +			pim_msdp_sa_state_timer_setup(sa, false /* start */); +			rp.s_addr = INADDR_ANY; +			pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp); +			/* if peer ref was removed we need to remove the msdp +			 * reference on the +			 * msdp entry */ +			update_up = true; +		} +	} + +	sa->flags &= ~flags; +	if (update_up) { +		pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); +	} + +	if (!(sa->flags & PIM_MSDP_SAF_REF)) { +		pim_msdp_sa_del(sa); +	} +} + +void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, +		     struct in_addr rp) +{ +	struct pim_msdp_sa *sa; + +	sa = pim_msdp_sa_add(sg, rp); +	if (!sa) { +		return; +	} + +	/* reference it */ +	if (mp) { +		if (!(sa->flags & PIM_MSDP_SAF_PEER)) { +			sa->flags |= PIM_MSDP_SAF_PEER; +			if (PIM_DEBUG_MSDP_EVENTS) { +				zlog_debug("MSDP SA %s added by peer", +					   sa->sg_str); +			} +		} +		pim_msdp_sa_peer_ip_set(sa, mp, rp); +		/* start/re-start the state timer to prevent cache expiry */ +		pim_msdp_sa_state_timer_setup(sa, true /* start */); +		/* We re-evaluate SA "SPT-trigger" everytime we hear abt it from +		 * a +		 * peer. XXX: If this becomes too much of a periodic overhead we +		 * can make it event based */ +		pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref"); +	} else { +		if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { +			sa->flags |= PIM_MSDP_SAF_LOCAL; +			++msdp->local_cnt; +			if (PIM_DEBUG_MSDP_EVENTS) { +				zlog_debug("MSDP SA %s added locally", +					   sa->sg_str); +			} +			/* send an immediate SA update to peers */ +			pim_msdp_pkt_sa_tx_one(sa); +		} +		sa->flags &= ~PIM_MSDP_SAF_STALE; +	}  }  /* The following criteria must be met to originate an SA from the MSDP @@ -431,93 +436,100 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,   *    b. We rxed a pim register (null or data encapsulated) within the last   *       (3 * (1.5 * register_suppression_timer))).   */ -static bool -pim_msdp_sa_local_add_ok(struct pim_upstream *up) +static bool pim_msdp_sa_local_add_ok(struct pim_upstream *up)  { -  if (!(msdp->flags & PIM_MSDPF_ENABLE)) { -    return false; -  } +	if (!(msdp->flags & PIM_MSDPF_ENABLE)) { +		return false; +	} -  if (!up->t_ka_timer) { -    /* stream is not active */ -    return false; -  } +	if (!up->t_ka_timer) { +		/* stream is not active */ +		return false; +	} -  if (!I_am_RP(up->sg.grp)) { -    /* we are not RP for the group */ -    return false; -  } +	if (!I_am_RP(up->sg.grp)) { +		/* we are not RP for the group */ +		return false; +	} -  /* we are the FHR-DR for this stream  or we are RP and have seen registers -   * from a FHR for this source */ -  if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || up->t_msdp_reg_timer) { -    return true; -  } +	/* we are the FHR-DR for this stream  or we are RP and have seen +	 * registers +	 * from a FHR for this source */ +	if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || up->t_msdp_reg_timer) { +		return true; +	} -  return false; +	return false;  } -static void -pim_msdp_sa_local_add(struct prefix_sg *sg) +static void pim_msdp_sa_local_add(struct prefix_sg *sg)  { -  struct in_addr rp; -  rp.s_addr = 0; -  pim_msdp_sa_ref(NULL /* mp */, sg, rp); +	struct in_addr rp; +	rp.s_addr = 0; +	pim_msdp_sa_ref(NULL /* mp */, sg, rp);  } -void -pim_msdp_sa_local_del(struct prefix_sg *sg) +void pim_msdp_sa_local_del(struct prefix_sg *sg)  { -  struct pim_msdp_sa *sa; +	struct pim_msdp_sa *sa; -  sa = pim_msdp_sa_find(sg); -  if (sa) { -    pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); -  } +	sa = pim_msdp_sa_find(sg); +	if (sa) { +		pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); +	}  }  /* we need to be very cautious with this API as SA del too can trigger an   * upstream del and we will get stuck in a simple loop */ -static void -pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) -{ -  struct pim_msdp_sa *sa; - -  sa = pim_msdp_sa_find(sg); -  if (sa) { -    if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP local sa %s del on up del", sa->sg_str); -    } - -    /* if there is no local reference escape */ -    if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { -      if (PIM_DEBUG_MSDP_INTERNAL) { -        zlog_debug("MSDP local sa %s del; no local ref", sa->sg_str); -      } -      return; -    } - -    if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { -      /* MSDP is the one that triggered the upstream del. if this happens -       * we most certainly have a bug in the PIM upstream state machine. We -       * will not have a local reference unless the KAT is running. And if the -       * KAT is running there MUST be an additional source-stream reference to -       * the flow. Accounting for such cases requires lot of changes; perhaps -       * address this in the next release? - XXX  */ -      zlog_err("MSDP sa %s SPT teardown is causing the local entry to be removed", sa->sg_str); -      return; -    } - -    /* we are dropping the sa on upstream del we should not have an -     * upstream reference */ -    if (sa->up) { -      if (PIM_DEBUG_MSDP_INTERNAL) { -        zlog_debug("MSDP local sa %s del; up non-NULL", sa->sg_str); -      } -      sa->up = NULL; -    } -    pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); -  } +static void pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) +{ +	struct pim_msdp_sa *sa; + +	sa = pim_msdp_sa_find(sg); +	if (sa) { +		if (PIM_DEBUG_MSDP_INTERNAL) { +			zlog_debug("MSDP local sa %s del on up del", +				   sa->sg_str); +		} + +		/* if there is no local reference escape */ +		if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { +			if (PIM_DEBUG_MSDP_INTERNAL) { +				zlog_debug("MSDP local sa %s del; no local ref", +					   sa->sg_str); +			} +			return; +		} + +		if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { +			/* MSDP is the one that triggered the upstream del. if +			 * this happens +			 * we most certainly have a bug in the PIM upstream +			 * state machine. We +			 * will not have a local reference unless the KAT is +			 * running. And if the +			 * KAT is running there MUST be an additional +			 * source-stream reference to +			 * the flow. Accounting for such cases requires lot of +			 * changes; perhaps +			 * address this in the next release? - XXX  */ +			zlog_err( +				"MSDP sa %s SPT teardown is causing the local entry to be removed", +				sa->sg_str); +			return; +		} + +		/* we are dropping the sa on upstream del we should not have an +		 * upstream reference */ +		if (sa->up) { +			if (PIM_DEBUG_MSDP_INTERNAL) { +				zlog_debug("MSDP local sa %s del; up non-NULL", +					   sa->sg_str); +			} +			sa->up = NULL; +		} +		pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); +	}  }  /* Local SA qualification needs to be re-evaluated when - @@ -529,1072 +541,1045 @@ pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg)   *    FHR is also the RP.   * 4. When msdp_reg timer is started or stopped   */ -void -pim_msdp_sa_local_update(struct pim_upstream *up) +void pim_msdp_sa_local_update(struct pim_upstream *up)  { -  if (pim_msdp_sa_local_add_ok(up)) { -    pim_msdp_sa_local_add(&up->sg); -  } else { -    pim_msdp_sa_local_del(&up->sg); -  } +	if (pim_msdp_sa_local_add_ok(up)) { +		pim_msdp_sa_local_add(&up->sg); +	} else { +		pim_msdp_sa_local_del(&up->sg); +	}  } -static void -pim_msdp_sa_local_setup(void) +static void pim_msdp_sa_local_setup(void)  { -  struct pim_upstream *up; -  struct listnode *up_node; +	struct pim_upstream *up; +	struct listnode *up_node; -  for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { -    pim_msdp_sa_local_update(up); -  } +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { +		pim_msdp_sa_local_update(up); +	}  }  /* whenever the RP changes we need to re-evaluate the "local" SA-cache */  /* XXX: needs to be tested */ -void -pim_msdp_i_am_rp_changed(void) -{ -  struct listnode *sanode; -  struct listnode *nextnode; -  struct pim_msdp_sa *sa; - -  if (!(msdp->flags & PIM_MSDPF_ENABLE)) { -    /* if the feature is not enabled do nothing */ -    return; -  } - -  if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP i_am_rp changed");  -  } - -  /* mark all local entries as stale */ -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    if (sa->flags & PIM_MSDP_SAF_LOCAL) { -      sa->flags |= PIM_MSDP_SAF_STALE; -    } -  } - -  /* re-setup local SA entries */ -  pim_msdp_sa_local_setup(); - -  for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, sa)) { -    /* purge stale SA entries */ -    if (sa->flags & PIM_MSDP_SAF_STALE) { -      /* clear the stale flag; the entry may be kept even after -       * "local-deref" */ -      sa->flags &= ~PIM_MSDP_SAF_STALE; -      /* sa_deref can end up freeing the sa; so don't access contents after */ -      pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); -    } else { -      /* if the souce is still active check if we can influence SPT */ -      pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "rp-change"); -    } -  } +void pim_msdp_i_am_rp_changed(void) +{ +	struct listnode *sanode; +	struct listnode *nextnode; +	struct pim_msdp_sa *sa; + +	if (!(msdp->flags & PIM_MSDPF_ENABLE)) { +		/* if the feature is not enabled do nothing */ +		return; +	} + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP i_am_rp changed"); +	} + +	/* mark all local entries as stale */ +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		if (sa->flags & PIM_MSDP_SAF_LOCAL) { +			sa->flags |= PIM_MSDP_SAF_STALE; +		} +	} + +	/* re-setup local SA entries */ +	pim_msdp_sa_local_setup(); + +	for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, sa)) { +		/* purge stale SA entries */ +		if (sa->flags & PIM_MSDP_SAF_STALE) { +			/* clear the stale flag; the entry may be kept even +			 * after +			 * "local-deref" */ +			sa->flags &= ~PIM_MSDP_SAF_STALE; +			/* sa_deref can end up freeing the sa; so don't access +			 * contents after */ +			pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); +		} else { +			/* if the souce is still active check if we can +			 * influence SPT */ +			pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, +						    "rp-change"); +		} +	}  }  /* We track the join state of (*, G) entries. If G has sources in the SA-cache   * we need to setup or teardown SPT when the JoinDesired status changes for   * (*, G) */ -void -pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) -{ -  struct listnode *sanode; -  struct pim_msdp_sa *sa; - -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP join state changed for %s", xg_up->sg_str); -  } - -  /* If this is not really an XG entry just move on */ -  if ((xg_up->sg.src.s_addr != INADDR_ANY) || -      (xg_up->sg.grp.s_addr == INADDR_ANY)) { -    return; -  } - -  /* XXX: Need to maintain SAs per-group to avoid all this unnecessary -   * walking */ -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { -      continue; -    } -    pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); -  } -} - -static void -pim_msdp_up_xg_del(struct prefix_sg *sg) -{ -  struct listnode *sanode; -  struct pim_msdp_sa *sa; - -  if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP %s del", pim_str_sg_dump(sg));  -  } - -  /* If this is not really an XG entry just move on */ -  if ((sg->src.s_addr != INADDR_ANY) || -      (sg->grp.s_addr == INADDR_ANY)) { -    return; -  } - -  /* XXX: Need to maintain SAs per-group to avoid all this unnecessary -   * walking */ -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    if (sa->sg.grp.s_addr != sg->grp.s_addr) { -      continue; -    } -    pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change"); -  } -} - -void -pim_msdp_up_del(struct prefix_sg *sg) -{ -  if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); -  } -  if (sg->src.s_addr == INADDR_ANY) { -    pim_msdp_up_xg_del(sg); -  } else { -    pim_msdp_sa_local_del_on_up_del(sg); -  } +void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) +{ +	struct listnode *sanode; +	struct pim_msdp_sa *sa; + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP join state changed for %s", xg_up->sg_str); +	} + +	/* If this is not really an XG entry just move on */ +	if ((xg_up->sg.src.s_addr != INADDR_ANY) +	    || (xg_up->sg.grp.s_addr == INADDR_ANY)) { +		return; +	} + +	/* XXX: Need to maintain SAs per-group to avoid all this unnecessary +	 * walking */ +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { +			continue; +		} +		pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); +	} +} + +static void pim_msdp_up_xg_del(struct prefix_sg *sg) +{ +	struct listnode *sanode; +	struct pim_msdp_sa *sa; + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP %s del", pim_str_sg_dump(sg)); +	} + +	/* If this is not really an XG entry just move on */ +	if ((sg->src.s_addr != INADDR_ANY) || (sg->grp.s_addr == INADDR_ANY)) { +		return; +	} + +	/* XXX: Need to maintain SAs per-group to avoid all this unnecessary +	 * walking */ +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		if (sa->sg.grp.s_addr != sg->grp.s_addr) { +			continue; +		} +		pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change"); +	} +} + +void pim_msdp_up_del(struct prefix_sg *sg) +{ +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); +	} +	if (sg->src.s_addr == INADDR_ANY) { +		pim_msdp_up_xg_del(sg); +	} else { +		pim_msdp_sa_local_del_on_up_del(sg); +	}  }  /* sa hash and peer list helpers */ -static unsigned int -pim_msdp_sa_hash_key_make(void *p) +static unsigned int pim_msdp_sa_hash_key_make(void *p)  { -  struct pim_msdp_sa *sa = p; +	struct pim_msdp_sa *sa = p; -  return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); +	return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0));  } -static int -pim_msdp_sa_hash_eq(const void *p1, const void *p2) +static int pim_msdp_sa_hash_eq(const void *p1, const void *p2)  { -  const struct pim_msdp_sa *sa1 = p1; -  const struct pim_msdp_sa *sa2 = p2; +	const struct pim_msdp_sa *sa1 = p1; +	const struct pim_msdp_sa *sa2 = p2; -  return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) && -          (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr)); +	return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) +		&& (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr));  } -static int -pim_msdp_sa_comp(const void *p1, const void *p2) +static int pim_msdp_sa_comp(const void *p1, const void *p2)  { -  const struct pim_msdp_sa *sa1 = p1; -  const struct pim_msdp_sa *sa2 = p2; +	const struct pim_msdp_sa *sa1 = p1; +	const struct pim_msdp_sa *sa2 = p2; -  if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) -    return -1; +	if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) +		return -1; -  if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) -    return 1; +	if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) +		return 1; -  if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) -    return -1; +	if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) +		return -1; -  if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) -    return 1; +	if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) +		return 1; -  return 0; +	return 0;  }  /* RFC-3618:Sec-10.1.3 - Peer-RPF forwarding */  /* XXX: this can use a bit of refining and extensions */ -bool -pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp) +bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp)  { -  if (mp->peer.s_addr == rp.s_addr) { -    return true; -  } +	if (mp->peer.s_addr == rp.s_addr) { +		return true; +	} -  return false; +	return false;  } -   +  /************************ Peer session management **************************/ -char * -pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size) -{ -  switch (state) { -    case PIM_MSDP_DISABLED: -      snprintf(buf, buf_size, "%s", "disabled"); -      break; -    case PIM_MSDP_INACTIVE: -      snprintf(buf, buf_size, "%s", "inactive"); -      break; -    case PIM_MSDP_LISTEN: -      snprintf(buf, buf_size, "%s", "listen"); -      break; -    case PIM_MSDP_CONNECTING: -      snprintf(buf, buf_size, "%s", "connecting"); -      break; -    case PIM_MSDP_ESTABLISHED: -      snprintf(buf, buf_size, "%s", "established"); -      break; -    default: -      snprintf(buf, buf_size, "unk-%d", state); -  } -  return buf; -} - -char * -pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format) -{ -  char peer_str[INET_ADDRSTRLEN]; -  char local_str[INET_ADDRSTRLEN]; - -  pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); -  if (long_format) { -    pim_inet4_dump("<local?>", mp->local, local_str, sizeof(local_str)); -    snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", -        peer_str, local_str, mp->mesh_group_name); -  } else { -    snprintf(buf, buf_size, "MSDP peer %s", peer_str); -  } - -  return buf; -} - -static void -pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) -{ -  char state_str[PIM_MSDP_STATE_STRLEN]; - -  pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); -  zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str); +char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, +			  int buf_size) +{ +	switch (state) { +	case PIM_MSDP_DISABLED: +		snprintf(buf, buf_size, "%s", "disabled"); +		break; +	case PIM_MSDP_INACTIVE: +		snprintf(buf, buf_size, "%s", "inactive"); +		break; +	case PIM_MSDP_LISTEN: +		snprintf(buf, buf_size, "%s", "listen"); +		break; +	case PIM_MSDP_CONNECTING: +		snprintf(buf, buf_size, "%s", "connecting"); +		break; +	case PIM_MSDP_ESTABLISHED: +		snprintf(buf, buf_size, "%s", "established"); +		break; +	default: +		snprintf(buf, buf_size, "unk-%d", state); +	} +	return buf; +} + +char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, +			     bool long_format) +{ +	char peer_str[INET_ADDRSTRLEN]; +	char local_str[INET_ADDRSTRLEN]; + +	pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str)); +	if (long_format) { +		pim_inet4_dump("<local?>", mp->local, local_str, +			       sizeof(local_str)); +		snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", peer_str, +			 local_str, mp->mesh_group_name); +	} else { +		snprintf(buf, buf_size, "MSDP peer %s", peer_str); +	} + +	return buf; +} + +static void pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) +{ +	char state_str[PIM_MSDP_STATE_STRLEN]; + +	pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); +	zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str);  }  /* MSDP Connection State Machine actions (defined in RFC-3618:Sec-11.2) */  /* 11.2.A2: active peer - start connect retry timer; when the timer fires   * a tcp connection will be made */ -static void -pim_msdp_peer_connect(struct pim_msdp_peer *mp) +static void pim_msdp_peer_connect(struct pim_msdp_peer *mp)  { -  mp->state = PIM_MSDP_CONNECTING; -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_peer_state_chg_log(mp); -  } +	mp->state = PIM_MSDP_CONNECTING; +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_peer_state_chg_log(mp); +	} -  pim_msdp_peer_cr_timer_setup(mp, true /* start */); +	pim_msdp_peer_cr_timer_setup(mp, true /* start */);  }  /* 11.2.A3: passive peer - just listen for connections */ -static void -pim_msdp_peer_listen(struct pim_msdp_peer *mp) +static void pim_msdp_peer_listen(struct pim_msdp_peer *mp)  { -  mp->state = PIM_MSDP_LISTEN; -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_peer_state_chg_log(mp); -  } +	mp->state = PIM_MSDP_LISTEN; +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_peer_state_chg_log(mp); +	} -  /* this is interntionally asymmetric i.e. we set up listen-socket when the -  * first listening peer is configured; but don't bother tearing it down when -  * all the peers go down */ -  pim_msdp_sock_listen(); +	/* this is interntionally asymmetric i.e. we set up listen-socket when +	* the +	* first listening peer is configured; but don't bother tearing it down +	* when +	* all the peers go down */ +	pim_msdp_sock_listen();  }  /* 11.2.A4 and 11.2.A5: transition active or passive peer to   * established state */ -void -pim_msdp_peer_established(struct pim_msdp_peer *mp) +void pim_msdp_peer_established(struct pim_msdp_peer *mp)  { -  if (mp->state != PIM_MSDP_ESTABLISHED) { -    ++mp->est_flaps; -  } +	if (mp->state != PIM_MSDP_ESTABLISHED) { +		++mp->est_flaps; +	} -  mp->state = PIM_MSDP_ESTABLISHED; -  mp->uptime = pim_time_monotonic_sec(); +	mp->state = PIM_MSDP_ESTABLISHED; +	mp->uptime = pim_time_monotonic_sec(); -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_peer_state_chg_log(mp); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_peer_state_chg_log(mp); +	} -  /* stop retry timer on active peers */ -  pim_msdp_peer_cr_timer_setup(mp, false /* start */); +	/* stop retry timer on active peers */ +	pim_msdp_peer_cr_timer_setup(mp, false /* start */); -  /* send KA; start KA and hold timers */ -  pim_msdp_pkt_ka_tx(mp); -  pim_msdp_peer_ka_timer_setup(mp, true /* start */); -  pim_msdp_peer_hold_timer_setup(mp, true /* start */); +	/* send KA; start KA and hold timers */ +	pim_msdp_pkt_ka_tx(mp); +	pim_msdp_peer_ka_timer_setup(mp, true /* start */); +	pim_msdp_peer_hold_timer_setup(mp, true /* start */); -  pim_msdp_pkt_sa_tx_to_one_peer(mp); +	pim_msdp_pkt_sa_tx_to_one_peer(mp); -  PIM_MSDP_PEER_WRITE_ON(mp); -  PIM_MSDP_PEER_READ_ON(mp); +	PIM_MSDP_PEER_WRITE_ON(mp); +	PIM_MSDP_PEER_READ_ON(mp);  }  /* 11.2.A6, 11.2.A7 and 11.2.A8: shutdown the peer tcp connection */ -void -pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) -{ -  if (chg_state) { -    if (mp->state == PIM_MSDP_ESTABLISHED) { -      ++mp->est_flaps; -    } -    mp->state = PIM_MSDP_INACTIVE; -    if (PIM_DEBUG_MSDP_EVENTS) { -      pim_msdp_peer_state_chg_log(mp); -    } -  } - -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s pim_msdp_peer_stop_tcp_conn", mp->key_str); -  } -  /* stop read and write threads */ -  PIM_MSDP_PEER_READ_OFF(mp); -  PIM_MSDP_PEER_WRITE_OFF(mp); - -  /* reset buffers */ -  mp->packet_size = 0; -  if (mp->ibuf) -    stream_reset(mp->ibuf); -  if (mp->obuf) -    stream_fifo_clean(mp->obuf); - -  /* stop all peer timers */ -  pim_msdp_peer_ka_timer_setup(mp, false /* start */); -  pim_msdp_peer_cr_timer_setup(mp, false /* start */); -  pim_msdp_peer_hold_timer_setup(mp, false /* start */); - -  /* close connection */ -  if (mp->fd >= 0) { -    close(mp->fd); -    mp->fd = -1; -  } +void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) +{ +	if (chg_state) { +		if (mp->state == PIM_MSDP_ESTABLISHED) { +			++mp->est_flaps; +		} +		mp->state = PIM_MSDP_INACTIVE; +		if (PIM_DEBUG_MSDP_EVENTS) { +			pim_msdp_peer_state_chg_log(mp); +		} +	} + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s pim_msdp_peer_stop_tcp_conn", +			   mp->key_str); +	} +	/* stop read and write threads */ +	PIM_MSDP_PEER_READ_OFF(mp); +	PIM_MSDP_PEER_WRITE_OFF(mp); + +	/* reset buffers */ +	mp->packet_size = 0; +	if (mp->ibuf) +		stream_reset(mp->ibuf); +	if (mp->obuf) +		stream_fifo_clean(mp->obuf); + +	/* stop all peer timers */ +	pim_msdp_peer_ka_timer_setup(mp, false /* start */); +	pim_msdp_peer_cr_timer_setup(mp, false /* start */); +	pim_msdp_peer_hold_timer_setup(mp, false /* start */); + +	/* close connection */ +	if (mp->fd >= 0) { +		close(mp->fd); +		mp->fd = -1; +	}  }  /* RFC-3618:Sec-5.6 - stop the peer tcp connection and startover */ -void -pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) +void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str)  { -  if (PIM_DEBUG_EVENTS) { -    zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str); -    snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); -  } +	if (PIM_DEBUG_EVENTS) { +		zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str); +		snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); +	} -  /* close the connection and transition to listening or connecting */ -  pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); -  if (PIM_MSDP_PEER_IS_LISTENER(mp)) { -    pim_msdp_peer_listen(mp); -  } else { -    pim_msdp_peer_connect(mp); -  } +	/* close the connection and transition to listening or connecting */ +	pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); +	if (PIM_MSDP_PEER_IS_LISTENER(mp)) { +		pim_msdp_peer_listen(mp); +	} else { +		pim_msdp_peer_connect(mp); +	}  } -static void -pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, const char *timer_str) +static void pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, +					   const char *timer_str)  { -  zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str); +	zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str);  }  /* RFC-3618:Sec-5.4 - peer hold timer */ -static int -pim_msdp_peer_hold_timer_cb(struct thread *t) +static int pim_msdp_peer_hold_timer_cb(struct thread *t)  { -  struct pim_msdp_peer *mp; +	struct pim_msdp_peer *mp; -  mp = THREAD_ARG(t); +	mp = THREAD_ARG(t); -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_peer_timer_expiry_log(mp, "hold"); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_peer_timer_expiry_log(mp, "hold"); +	} -  if (mp->state != PIM_MSDP_ESTABLISHED) { -    return 0; -  } +	if (mp->state != PIM_MSDP_ESTABLISHED) { +		return 0; +	} -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_peer_state_chg_log(mp); -  } -  pim_msdp_peer_reset_tcp_conn(mp, "ht-expired"); -  return 0; +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_peer_state_chg_log(mp); +	} +	pim_msdp_peer_reset_tcp_conn(mp, "ht-expired"); +	return 0;  } -static void -pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start)  { -  THREAD_OFF(mp->hold_timer); -  if (start) { -    thread_add_timer(msdp->master, pim_msdp_peer_hold_timer_cb, mp, -                     PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer); -  } +	THREAD_OFF(mp->hold_timer); +	if (start) { +		thread_add_timer(msdp->master, pim_msdp_peer_hold_timer_cb, mp, +				 PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer); +	}  }  /* RFC-3618:Sec-5.5 - peer keepalive timer */ -static int -pim_msdp_peer_ka_timer_cb(struct thread *t) +static int pim_msdp_peer_ka_timer_cb(struct thread *t)  { -  struct pim_msdp_peer *mp; +	struct pim_msdp_peer *mp; -  mp = THREAD_ARG(t); +	mp = THREAD_ARG(t); -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_peer_timer_expiry_log(mp, "ka"); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_peer_timer_expiry_log(mp, "ka"); +	} -  pim_msdp_pkt_ka_tx(mp); -  pim_msdp_peer_ka_timer_setup(mp, true /* start */); -  return 0; +	pim_msdp_pkt_ka_tx(mp); +	pim_msdp_peer_ka_timer_setup(mp, true /* start */); +	return 0;  } -static void -pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start)  { -  THREAD_OFF(mp->ka_timer); -  if (start) { -    thread_add_timer(msdp->master, pim_msdp_peer_ka_timer_cb, mp, -                     PIM_MSDP_PEER_KA_TIME, &mp->ka_timer); -  } +	THREAD_OFF(mp->ka_timer); +	if (start) { +		thread_add_timer(msdp->master, pim_msdp_peer_ka_timer_cb, mp, +				 PIM_MSDP_PEER_KA_TIME, &mp->ka_timer); +	}  } -static void -pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) +static void pim_msdp_peer_active_connect(struct pim_msdp_peer *mp)  { -  int rc; -  ++mp->conn_attempts; -  rc = pim_msdp_sock_connect(mp); +	int rc; +	++mp->conn_attempts; +	rc = pim_msdp_sock_connect(mp); -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s pim_msdp_peer_active_connect: %d", mp->key_str, rc); -  } +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s pim_msdp_peer_active_connect: %d", +			   mp->key_str, rc); +	} -  switch (rc) { -    case connect_error: -    case -1: -      /* connect failed restart the connect-retry timer */ -      pim_msdp_peer_cr_timer_setup(mp, true /* start */); -      break; +	switch (rc) { +	case connect_error: +	case -1: +		/* connect failed restart the connect-retry timer */ +		pim_msdp_peer_cr_timer_setup(mp, true /* start */); +		break; -    case connect_success: -      /* connect was sucessful move to established */ -      pim_msdp_peer_established(mp); -      break; +	case connect_success: +		/* connect was sucessful move to established */ +		pim_msdp_peer_established(mp); +		break; -    case connect_in_progress: -      /* for NB content we need to wait till sock is readable or -       * writeable */ -      PIM_MSDP_PEER_WRITE_ON(mp); -      PIM_MSDP_PEER_READ_ON(mp); -      /* also restart connect-retry timer to reset the socket if connect is -       * not sucessful */ -      pim_msdp_peer_cr_timer_setup(mp, true /* start */); -      break; -  } +	case connect_in_progress: +		/* for NB content we need to wait till sock is readable or +		 * writeable */ +		PIM_MSDP_PEER_WRITE_ON(mp); +		PIM_MSDP_PEER_READ_ON(mp); +		/* also restart connect-retry timer to reset the socket if +		 * connect is +		 * not sucessful */ +		pim_msdp_peer_cr_timer_setup(mp, true /* start */); +		break; +	}  }  /* RFC-3618:Sec-5.6 - connection retry on active peer */ -static int -pim_msdp_peer_cr_timer_cb(struct thread *t) +static int pim_msdp_peer_cr_timer_cb(struct thread *t)  { -  struct pim_msdp_peer *mp; +	struct pim_msdp_peer *mp; -  mp = THREAD_ARG(t); +	mp = THREAD_ARG(t); -  if (PIM_DEBUG_MSDP_EVENTS) { -    pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); +	} -  if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) { -    return 0; -  } +	if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) { +		return 0; +	} -  pim_msdp_peer_active_connect(mp); -  return 0; +	pim_msdp_peer_active_connect(mp); +	return 0;  } -static void -pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start)  { -  THREAD_OFF(mp->cr_timer); -  if (start) { -    thread_add_timer(msdp->master, pim_msdp_peer_cr_timer_cb, mp, -                     PIM_MSDP_PEER_CONNECT_RETRY_TIME, &mp->cr_timer); -  } +	THREAD_OFF(mp->cr_timer); +	if (start) { +		thread_add_timer(msdp->master, pim_msdp_peer_cr_timer_cb, mp, +				 PIM_MSDP_PEER_CONNECT_RETRY_TIME, +				 &mp->cr_timer); +	}  }  /* if a valid packet is rxed from the peer we can restart hold timer */ -void -pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp) +void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp)  { -  if (mp->state == PIM_MSDP_ESTABLISHED) { -    pim_msdp_peer_hold_timer_setup(mp, true /* start */); -  } +	if (mp->state == PIM_MSDP_ESTABLISHED) { +		pim_msdp_peer_hold_timer_setup(mp, true /* start */); +	}  }  /* if a valid packet is txed to the peer we can restart ka timer and avoid   * unnecessary ka noise in the network */ -void -pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp) +void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp)  { -  if (mp->state == PIM_MSDP_ESTABLISHED) { -    pim_msdp_peer_ka_timer_setup(mp, true /* start */); -    if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP ka timer restart on pkt tx to %s", mp->key_str); -    } -  } +	if (mp->state == PIM_MSDP_ESTABLISHED) { +		pim_msdp_peer_ka_timer_setup(mp, true /* start */); +		if (PIM_DEBUG_MSDP_INTERNAL) { +			zlog_debug("MSDP ka timer restart on pkt tx to %s", +				   mp->key_str); +		} +	}  }  static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr)  { -  sockunion_init(su); -  su->sin.sin_addr = addr; -  su->sin.sin_family = AF_INET; +	sockunion_init(su); +	su->sin.sin_addr = addr; +	su->sin.sin_family = AF_INET;  #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN -  su->sin.sin_len = sizeof(struct sockaddr_in); +	su->sin.sin_len = sizeof(struct sockaddr_in);  #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */  }  /* 11.2.A1: create a new peer and transition state to listen or connecting */ -static enum pim_msdp_err -pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, -                  const char *mesh_group_name, struct pim_msdp_peer **mp_p) -{ -  struct pim_msdp_peer *mp; - -  pim_msdp_enable(); - -  mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); -  if (!mp) { -    zlog_err("%s: PIM XCALLOC(%zu) failure", -             __PRETTY_FUNCTION__, sizeof(*mp)); -    return PIM_MSDP_ERR_OOM; -  } - -  mp->peer = peer_addr; -  pim_inet4_dump("<peer?>", mp->peer, mp->key_str, sizeof(mp->key_str)); -  pim_msdp_addr2su(&mp->su_peer, mp->peer); -  mp->local = local_addr; -  /* XXX: originator_id setting needs to move to the mesh group */ -  msdp->originator_id = local_addr; -  pim_msdp_addr2su(&mp->su_local, mp->local); -  mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); -  mp->state = PIM_MSDP_INACTIVE; -  mp->fd = -1; -  strcpy(mp->last_reset, "-"); -  /* higher IP address is listener */ -  if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { -    mp->flags |= PIM_MSDP_PEERF_LISTENER; -  } - -  /* setup packet buffers */ -  mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); -  mp->obuf = stream_fifo_new(); - -  /* insert into misc tables for easy access */ -  mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); -  listnode_add_sort(msdp->peer_list, mp); - -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP peer %s created", mp->key_str); - -    pim_msdp_peer_state_chg_log(mp); -  } - -  /* fireup the connect state machine */ -  if (PIM_MSDP_PEER_IS_LISTENER(mp)) { -    pim_msdp_peer_listen(mp); -  } else { -    pim_msdp_peer_connect(mp); -  } -  if (mp_p) { -    *mp_p = mp; -  } -  return PIM_MSDP_ERR_NONE; -} - -struct pim_msdp_peer * -pim_msdp_peer_find(struct in_addr peer_addr) -{ -  struct pim_msdp_peer lookup; - -  lookup.peer = peer_addr; -  return hash_lookup(msdp->peer_hash, &lookup); +static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr, +					   struct in_addr local_addr, +					   const char *mesh_group_name, +					   struct pim_msdp_peer **mp_p) +{ +	struct pim_msdp_peer *mp; + +	pim_msdp_enable(); + +	mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); +	if (!mp) { +		zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, +			 sizeof(*mp)); +		return PIM_MSDP_ERR_OOM; +	} + +	mp->peer = peer_addr; +	pim_inet4_dump("<peer?>", mp->peer, mp->key_str, sizeof(mp->key_str)); +	pim_msdp_addr2su(&mp->su_peer, mp->peer); +	mp->local = local_addr; +	/* XXX: originator_id setting needs to move to the mesh group */ +	msdp->originator_id = local_addr; +	pim_msdp_addr2su(&mp->su_local, mp->local); +	mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); +	mp->state = PIM_MSDP_INACTIVE; +	mp->fd = -1; +	strcpy(mp->last_reset, "-"); +	/* higher IP address is listener */ +	if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { +		mp->flags |= PIM_MSDP_PEERF_LISTENER; +	} + +	/* setup packet buffers */ +	mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); +	mp->obuf = stream_fifo_new(); + +	/* insert into misc tables for easy access */ +	mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); +	listnode_add_sort(msdp->peer_list, mp); + +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP peer %s created", mp->key_str); + +		pim_msdp_peer_state_chg_log(mp); +	} + +	/* fireup the connect state machine */ +	if (PIM_MSDP_PEER_IS_LISTENER(mp)) { +		pim_msdp_peer_listen(mp); +	} else { +		pim_msdp_peer_connect(mp); +	} +	if (mp_p) { +		*mp_p = mp; +	} +	return PIM_MSDP_ERR_NONE; +} + +struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr) +{ +	struct pim_msdp_peer lookup; + +	lookup.peer = peer_addr; +	return hash_lookup(msdp->peer_hash, &lookup);  }  /* add peer configuration if it doesn't already exist */ -enum pim_msdp_err -pim_msdp_peer_add(struct in_addr peer_addr, struct in_addr local_addr, -                  const char *mesh_group_name, struct pim_msdp_peer **mp_p) +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer_addr, +				    struct in_addr local_addr, +				    const char *mesh_group_name, +				    struct pim_msdp_peer **mp_p)  { -  struct pim_msdp_peer *mp; +	struct pim_msdp_peer *mp; -  if (mp_p) { -    *mp_p = NULL; -  } +	if (mp_p) { +		*mp_p = NULL; +	} -  if (peer_addr.s_addr == local_addr.s_addr) { -    /* skip session setup if config is invalid */ -    if (PIM_DEBUG_MSDP_EVENTS) { -      char peer_str[INET_ADDRSTRLEN]; +	if (peer_addr.s_addr == local_addr.s_addr) { +		/* skip session setup if config is invalid */ +		if (PIM_DEBUG_MSDP_EVENTS) { +			char peer_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<peer?>", peer_addr, peer_str, sizeof(peer_str)); -      zlog_debug("%s add skipped as DIP=SIP", peer_str); -    } -    return PIM_MSDP_ERR_SIP_EQ_DIP; -  } +			pim_inet4_dump("<peer?>", peer_addr, peer_str, +				       sizeof(peer_str)); +			zlog_debug("%s add skipped as DIP=SIP", peer_str); +		} +		return PIM_MSDP_ERR_SIP_EQ_DIP; +	} -  mp = pim_msdp_peer_find(peer_addr); -  if (mp) { -    if (mp_p) { -      *mp_p = mp; -    } -    return PIM_MSDP_ERR_PEER_EXISTS; -  } +	mp = pim_msdp_peer_find(peer_addr); +	if (mp) { +		if (mp_p) { +			*mp_p = mp; +		} +		return PIM_MSDP_ERR_PEER_EXISTS; +	} -  return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p); +	return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p);  }  /* release all mem associated with a peer */ -static void -pim_msdp_peer_free(struct pim_msdp_peer *mp) +static void pim_msdp_peer_free(struct pim_msdp_peer *mp)  { -  if (mp->ibuf) { -    stream_free(mp->ibuf); -  } +	if (mp->ibuf) { +		stream_free(mp->ibuf); +	} -  if (mp->obuf) { -    stream_fifo_free(mp->obuf); -  } +	if (mp->obuf) { +		stream_fifo_free(mp->obuf); +	} -  if (mp->mesh_group_name) { -    XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); -  } -  XFREE(MTYPE_PIM_MSDP_PEER, mp); +	if (mp->mesh_group_name) { +		XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); +	} +	XFREE(MTYPE_PIM_MSDP_PEER, mp);  }  /* delete the peer config */ -static enum pim_msdp_err -pim_msdp_peer_do_del(struct pim_msdp_peer *mp) +static enum pim_msdp_err pim_msdp_peer_do_del(struct pim_msdp_peer *mp)  { -  /* stop the tcp connection and shutdown all timers */ -  pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); +	/* stop the tcp connection and shutdown all timers */ +	pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); -  /* remove the session from various tables */ -  listnode_delete(msdp->peer_list, mp); -  hash_release(msdp->peer_hash, mp); +	/* remove the session from various tables */ +	listnode_delete(msdp->peer_list, mp); +	hash_release(msdp->peer_hash, mp); -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP peer %s deleted", mp->key_str); -  } +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP peer %s deleted", mp->key_str); +	} -  /* free up any associated memory */ -  pim_msdp_peer_free(mp); +	/* free up any associated memory */ +	pim_msdp_peer_free(mp); -  return PIM_MSDP_ERR_NONE; +	return PIM_MSDP_ERR_NONE;  } -enum pim_msdp_err -pim_msdp_peer_del(struct in_addr peer_addr) +enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr)  { -  struct pim_msdp_peer *mp; +	struct pim_msdp_peer *mp; -  mp = pim_msdp_peer_find(peer_addr); -  if (!mp) { -    return PIM_MSDP_ERR_NO_PEER; -  } +	mp = pim_msdp_peer_find(peer_addr); +	if (!mp) { +		return PIM_MSDP_ERR_NO_PEER; +	} -  return pim_msdp_peer_do_del(mp); +	return pim_msdp_peer_do_del(mp);  }  /* peer hash and peer list helpers */ -static unsigned int -pim_msdp_peer_hash_key_make(void *p) +static unsigned int pim_msdp_peer_hash_key_make(void *p)  { -  struct pim_msdp_peer *mp = p; -  return (jhash_1word(mp->peer.s_addr, 0)); +	struct pim_msdp_peer *mp = p; +	return (jhash_1word(mp->peer.s_addr, 0));  } -static int -pim_msdp_peer_hash_eq(const void *p1, const void *p2) +static int pim_msdp_peer_hash_eq(const void *p1, const void *p2)  { -  const struct pim_msdp_peer *mp1 = p1; -  const struct pim_msdp_peer *mp2 = p2; +	const struct pim_msdp_peer *mp1 = p1; +	const struct pim_msdp_peer *mp2 = p2; -  return (mp1->peer.s_addr == mp2->peer.s_addr); +	return (mp1->peer.s_addr == mp2->peer.s_addr);  } -static int -pim_msdp_peer_comp(const void *p1, const void *p2) +static int pim_msdp_peer_comp(const void *p1, const void *p2)  { -  const struct pim_msdp_peer *mp1 = p1; -  const struct pim_msdp_peer *mp2 = p2; +	const struct pim_msdp_peer *mp1 = p1; +	const struct pim_msdp_peer *mp2 = p2; -  if (ntohl(mp1->peer.s_addr) < ntohl(mp2->peer.s_addr)) -    return -1; +	if (ntohl(mp1->peer.s_addr) < ntohl(mp2->peer.s_addr)) +		return -1; -  if (ntohl(mp1->peer.s_addr) > ntohl(mp2->peer.s_addr)) -    return 1; +	if (ntohl(mp1->peer.s_addr) > ntohl(mp2->peer.s_addr)) +		return 1; -  return 0; +	return 0;  }  /************************** Mesh group management **************************/ -static void -pim_msdp_mg_free(struct pim_msdp_mg *mg) +static void pim_msdp_mg_free(struct pim_msdp_mg *mg)  { -  /* If the mesh-group has valid member or src_ip don't delete it */ -  if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { -    return; -  } +	/* If the mesh-group has valid member or src_ip don't delete it */ +	if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { +		return; +	} -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); -  } -  if (mg->mesh_group_name) -    XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); +	} +	if (mg->mesh_group_name) +		XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); -  if (mg->mbr_list) -    list_free(mg->mbr_list); +	if (mg->mbr_list) +		list_free(mg->mbr_list); -  XFREE(MTYPE_PIM_MSDP_MG, mg); -  msdp->mg = NULL; +	XFREE(MTYPE_PIM_MSDP_MG, mg); +	msdp->mg = NULL;  } -static struct pim_msdp_mg * -pim_msdp_mg_new(const char *mesh_group_name) +static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name)  { -  struct pim_msdp_mg *mg; +	struct pim_msdp_mg *mg; -  mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); -  if (!mg) { -    zlog_err("%s: PIM XCALLOC(%zu) failure", -             __PRETTY_FUNCTION__, sizeof(*mg)); -    return NULL; -  } +	mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); +	if (!mg) { +		zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, +			 sizeof(*mg)); +		return NULL; +	} -  mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); -  mg->mbr_list = list_new(); -  mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free; -  mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp; +	mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); +	mg->mbr_list = list_new(); +	mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free; +	mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp; -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); -  } -  return mg; +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); +	} +	return mg;  } -enum pim_msdp_err -pim_msdp_mg_del(const char *mesh_group_name) +enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name)  { -  struct pim_msdp_mg *mg = msdp->mg; -  struct pim_msdp_mg_mbr *mbr; +	struct pim_msdp_mg *mg = msdp->mg; +	struct pim_msdp_mg_mbr *mbr; -  if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { -    return PIM_MSDP_ERR_NO_MG; -  } +	if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { +		return PIM_MSDP_ERR_NO_MG; +	} -  /* delete all the mesh-group members */ -  while (!list_isempty(mg->mbr_list)) { -    mbr = listnode_head(mg->mbr_list); -    pim_msdp_mg_mbr_do_del(mg, mbr); -  } +	/* delete all the mesh-group members */ +	while (!list_isempty(mg->mbr_list)) { +		mbr = listnode_head(mg->mbr_list); +		pim_msdp_mg_mbr_do_del(mg, mbr); +	} -  /* clear src ip */ -  mg->src_ip.s_addr = INADDR_ANY; +	/* clear src ip */ +	mg->src_ip.s_addr = INADDR_ANY; -  /* free up the mesh-group */ -  pim_msdp_mg_free(mg); -  return PIM_MSDP_ERR_NONE; +	/* free up the mesh-group */ +	pim_msdp_mg_free(mg); +	return PIM_MSDP_ERR_NONE;  } -static enum pim_msdp_err -pim_msdp_mg_add(const char *mesh_group_name) +static enum pim_msdp_err pim_msdp_mg_add(const char *mesh_group_name)  { -  if (msdp->mg) { -    if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) { -      return PIM_MSDP_ERR_NONE; -    } -    /* currently only one mesh-group can exist at a time */ -    return PIM_MSDP_ERR_MAX_MESH_GROUPS; -  } +	if (msdp->mg) { +		if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) { +			return PIM_MSDP_ERR_NONE; +		} +		/* currently only one mesh-group can exist at a time */ +		return PIM_MSDP_ERR_MAX_MESH_GROUPS; +	} -  msdp->mg = pim_msdp_mg_new(mesh_group_name); -  if (!msdp->mg) { -    return PIM_MSDP_ERR_OOM; -  } +	msdp->mg = pim_msdp_mg_new(mesh_group_name); +	if (!msdp->mg) { +		return PIM_MSDP_ERR_OOM; +	} -  return PIM_MSDP_ERR_NONE; +	return PIM_MSDP_ERR_NONE;  } -static int -pim_msdp_mg_mbr_comp(const void *p1, const void *p2) +static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2)  { -  const struct pim_msdp_mg_mbr *mbr1 = p1; -  const struct pim_msdp_mg_mbr *mbr2 = p2; +	const struct pim_msdp_mg_mbr *mbr1 = p1; +	const struct pim_msdp_mg_mbr *mbr2 = p2; -  if (ntohl(mbr1->mbr_ip.s_addr) < ntohl(mbr2->mbr_ip.s_addr)) -    return -1; +	if (ntohl(mbr1->mbr_ip.s_addr) < ntohl(mbr2->mbr_ip.s_addr)) +		return -1; -  if (ntohl(mbr1->mbr_ip.s_addr) > ntohl(mbr2->mbr_ip.s_addr)) -    return 1; +	if (ntohl(mbr1->mbr_ip.s_addr) > ntohl(mbr2->mbr_ip.s_addr)) +		return 1; -  return 0; +	return 0;  } -static void -pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr) +static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr)  { -  XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr); +	XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr);  } -static struct pim_msdp_mg_mbr * -pim_msdp_mg_mbr_find(struct in_addr mbr_ip) +static struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_find(struct in_addr mbr_ip)  { -  struct pim_msdp_mg_mbr *mbr; -  struct listnode *mbr_node; +	struct pim_msdp_mg_mbr *mbr; +	struct listnode *mbr_node; -  if (!msdp->mg) { -    return NULL; -  } -  /* we can move this to a hash but considering that number of peers in -   * a mesh-group that seems like bit of an overkill */ -  for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) { -    if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { -      return mbr; -    } -  } -  return mbr; +	if (!msdp->mg) { +		return NULL; +	} +	/* we can move this to a hash but considering that number of peers in +	 * a mesh-group that seems like bit of an overkill */ +	for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) { +		if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { +			return mbr; +		} +	} +	return mbr;  } -enum pim_msdp_err -pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip) +enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, +				      struct in_addr mbr_ip)  { -  int rc; -  struct pim_msdp_mg_mbr *mbr; -  struct pim_msdp_mg *mg; +	int rc; +	struct pim_msdp_mg_mbr *mbr; +	struct pim_msdp_mg *mg; -  rc = pim_msdp_mg_add(mesh_group_name); -  if (rc != PIM_MSDP_ERR_NONE) { -    return rc; -  } +	rc = pim_msdp_mg_add(mesh_group_name); +	if (rc != PIM_MSDP_ERR_NONE) { +		return rc; +	} -  mg = msdp->mg; -  mbr = pim_msdp_mg_mbr_find(mbr_ip); -  if (mbr) { -    return PIM_MSDP_ERR_MG_MBR_EXISTS; -  } +	mg = msdp->mg; +	mbr = pim_msdp_mg_mbr_find(mbr_ip); +	if (mbr) { +		return PIM_MSDP_ERR_MG_MBR_EXISTS; +	} -  mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); -  if (!mbr) { -    zlog_err("%s: PIM XCALLOC(%zu) failure", -             __PRETTY_FUNCTION__, sizeof(*mbr)); -    /* if there are no references to the mg free it */ -    pim_msdp_mg_free(mg); -    return PIM_MSDP_ERR_OOM; -  } -  mbr->mbr_ip = mbr_ip; -  listnode_add_sort(mg->mbr_list, mbr); +	mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); +	if (!mbr) { +		zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, +			 sizeof(*mbr)); +		/* if there are no references to the mg free it */ +		pim_msdp_mg_free(mg); +		return PIM_MSDP_ERR_OOM; +	} +	mbr->mbr_ip = mbr_ip; +	listnode_add_sort(mg->mbr_list, mbr); -  /* if valid SIP has been configured add peer session */ -  if (mg->src_ip.s_addr != INADDR_ANY) { -    pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name, -                           &mbr->mp); -  } +	/* if valid SIP has been configured add peer session */ +	if (mg->src_ip.s_addr != INADDR_ANY) { +		pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name, +				  &mbr->mp); +	} -  if (PIM_DEBUG_MSDP_EVENTS) { -    char ip_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); -    zlog_debug("MSDP mesh-group %s mbr %s created", mg->mesh_group_name, ip_str); -  } -  ++mg->mbr_cnt; -  return PIM_MSDP_ERR_NONE; +	if (PIM_DEBUG_MSDP_EVENTS) { +		char ip_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); +		zlog_debug("MSDP mesh-group %s mbr %s created", +			   mg->mesh_group_name, ip_str); +	} +	++mg->mbr_cnt; +	return PIM_MSDP_ERR_NONE;  } -static void -pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr) +static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, +				   struct pim_msdp_mg_mbr *mbr)  { -  /* Delete active peer session if any */ -  if (mbr->mp) { -    pim_msdp_peer_do_del(mbr->mp); -  } +	/* Delete active peer session if any */ +	if (mbr->mp) { +		pim_msdp_peer_do_del(mbr->mp); +	} -  listnode_delete(mg->mbr_list, mbr); -  if (PIM_DEBUG_MSDP_EVENTS) { -    char ip_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); -    zlog_debug("MSDP mesh-group %s mbr %s deleted", mg->mesh_group_name, ip_str); -  } -  pim_msdp_mg_mbr_free(mbr); -  if (mg->mbr_cnt) { -    --mg->mbr_cnt; -  } +	listnode_delete(mg->mbr_list, mbr); +	if (PIM_DEBUG_MSDP_EVENTS) { +		char ip_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<mbr?>", mbr->mbr_ip, ip_str, sizeof(ip_str)); +		zlog_debug("MSDP mesh-group %s mbr %s deleted", +			   mg->mesh_group_name, ip_str); +	} +	pim_msdp_mg_mbr_free(mbr); +	if (mg->mbr_cnt) { +		--mg->mbr_cnt; +	}  } -enum pim_msdp_err -pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip) -{ -  struct pim_msdp_mg_mbr *mbr; -  struct pim_msdp_mg *mg = msdp->mg; - -  if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { -    return PIM_MSDP_ERR_NO_MG; -  } - -  mbr = pim_msdp_mg_mbr_find(mbr_ip); -  if (!mbr) { -    return PIM_MSDP_ERR_NO_MG_MBR; -  } - -  pim_msdp_mg_mbr_do_del(mg, mbr); -  /* if there are no references to the mg free it */ -  pim_msdp_mg_free(mg); - -  return PIM_MSDP_ERR_NONE; -} - -static void -pim_msdp_mg_src_do_del(void) -{ -  struct pim_msdp_mg_mbr *mbr; -  struct listnode *mbr_node; -  struct pim_msdp_mg *mg = msdp->mg; - -  /* SIP is being removed - tear down all active peer sessions */ -  for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { -    if (mbr->mp) { -      pim_msdp_peer_do_del(mbr->mp); -      mbr->mp = NULL; -    } -  } -  if (PIM_DEBUG_MSDP_EVENTS) { -    zlog_debug("MSDP mesh-group %s src cleared", mg->mesh_group_name); -  } -} - -enum pim_msdp_err -pim_msdp_mg_src_del(const char *mesh_group_name) -{ -  struct pim_msdp_mg *mg = msdp->mg; - -  if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { -    return PIM_MSDP_ERR_NO_MG; -  } - -  if (mg->src_ip.s_addr != INADDR_ANY) { -    mg->src_ip.s_addr = INADDR_ANY; -    pim_msdp_mg_src_do_del(); -    /* if there are no references to the mg free it */ -    pim_msdp_mg_free(mg); -  } -  return PIM_MSDP_ERR_NONE; -} - -enum pim_msdp_err -pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip) -{ -  int rc; -  struct pim_msdp_mg_mbr *mbr; -  struct listnode *mbr_node; -  struct pim_msdp_mg *mg; - -  if (src_ip.s_addr == INADDR_ANY) { -    pim_msdp_mg_src_del(mesh_group_name); -    return PIM_MSDP_ERR_NONE; -  } - -  rc = pim_msdp_mg_add(mesh_group_name); -  if (rc != PIM_MSDP_ERR_NONE) { -    return rc; -  } - -  mg = msdp->mg; -  if (mg->src_ip.s_addr != INADDR_ANY) { -    pim_msdp_mg_src_do_del(); -  } -  mg->src_ip = src_ip; +enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, +				      struct in_addr mbr_ip) +{ +	struct pim_msdp_mg_mbr *mbr; +	struct pim_msdp_mg *mg = msdp->mg; + +	if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { +		return PIM_MSDP_ERR_NO_MG; +	} + +	mbr = pim_msdp_mg_mbr_find(mbr_ip); +	if (!mbr) { +		return PIM_MSDP_ERR_NO_MG_MBR; +	} + +	pim_msdp_mg_mbr_do_del(mg, mbr); +	/* if there are no references to the mg free it */ +	pim_msdp_mg_free(mg); + +	return PIM_MSDP_ERR_NONE; +} + +static void pim_msdp_mg_src_do_del(void) +{ +	struct pim_msdp_mg_mbr *mbr; +	struct listnode *mbr_node; +	struct pim_msdp_mg *mg = msdp->mg; + +	/* SIP is being removed - tear down all active peer sessions */ +	for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { +		if (mbr->mp) { +			pim_msdp_peer_do_del(mbr->mp); +			mbr->mp = NULL; +		} +	} +	if (PIM_DEBUG_MSDP_EVENTS) { +		zlog_debug("MSDP mesh-group %s src cleared", +			   mg->mesh_group_name); +	} +} + +enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name) +{ +	struct pim_msdp_mg *mg = msdp->mg; + +	if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { +		return PIM_MSDP_ERR_NO_MG; +	} + +	if (mg->src_ip.s_addr != INADDR_ANY) { +		mg->src_ip.s_addr = INADDR_ANY; +		pim_msdp_mg_src_do_del(); +		/* if there are no references to the mg free it */ +		pim_msdp_mg_free(mg); +	} +	return PIM_MSDP_ERR_NONE; +} + +enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, +				      struct in_addr src_ip) +{ +	int rc; +	struct pim_msdp_mg_mbr *mbr; +	struct listnode *mbr_node; +	struct pim_msdp_mg *mg; + +	if (src_ip.s_addr == INADDR_ANY) { +		pim_msdp_mg_src_del(mesh_group_name); +		return PIM_MSDP_ERR_NONE; +	} + +	rc = pim_msdp_mg_add(mesh_group_name); +	if (rc != PIM_MSDP_ERR_NONE) { +		return rc; +	} + +	mg = msdp->mg; +	if (mg->src_ip.s_addr != INADDR_ANY) { +		pim_msdp_mg_src_do_del(); +	} +	mg->src_ip = src_ip; -  for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { -    pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name, -                           &mbr->mp); -  } +	for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { +		pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name, +				  &mbr->mp); +	} -  if (PIM_DEBUG_MSDP_EVENTS) { -    char ip_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", mg->src_ip, ip_str, sizeof(ip_str)); -    zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, ip_str); -  } -  return PIM_MSDP_ERR_NONE; +	if (PIM_DEBUG_MSDP_EVENTS) { +		char ip_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", mg->src_ip, ip_str, sizeof(ip_str)); +		zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, +			   ip_str); +	} +	return PIM_MSDP_ERR_NONE;  }  /*********************** MSDP feature APIs *********************************/ -int -pim_msdp_config_write(struct vty *vty) -{ -  struct listnode *mbrnode; -  struct pim_msdp_mg_mbr *mbr; -  struct pim_msdp_mg *mg = msdp->mg; -  char mbr_str[INET_ADDRSTRLEN]; -  char src_str[INET_ADDRSTRLEN]; -  int count = 0; - -  if (!mg) { -    return count; -  } - -  if (mg->src_ip.s_addr != INADDR_ANY) { -    pim_inet4_dump("<src?>", mg->src_ip, src_str, sizeof(src_str)); -    vty_out (vty, "ip msdp mesh-group %s source %s\n", -        mg->mesh_group_name, src_str); -    ++count; -  } - -  for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { -    pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); -    vty_out (vty, "ip msdp mesh-group %s member %s\n", -        mg->mesh_group_name, mbr_str); -    ++count; -  } -  return count; +int pim_msdp_config_write(struct vty *vty) +{ +	struct listnode *mbrnode; +	struct pim_msdp_mg_mbr *mbr; +	struct pim_msdp_mg *mg = msdp->mg; +	char mbr_str[INET_ADDRSTRLEN]; +	char src_str[INET_ADDRSTRLEN]; +	int count = 0; + +	if (!mg) { +		return count; +	} + +	if (mg->src_ip.s_addr != INADDR_ANY) { +		pim_inet4_dump("<src?>", mg->src_ip, src_str, sizeof(src_str)); +		vty_out(vty, "ip msdp mesh-group %s source %s\n", +			mg->mesh_group_name, src_str); +		++count; +	} + +	for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { +		pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); +		vty_out(vty, "ip msdp mesh-group %s member %s\n", +			mg->mesh_group_name, mbr_str); +		++count; +	} +	return count;  }  /* Enable feature including active/periodic timers etc. on the first peer   * config. Till then MSDP should just stay quiet. */ -static void -pim_msdp_enable(void) +static void pim_msdp_enable(void)  { -  if (msdp->flags & PIM_MSDPF_ENABLE) { -    /* feature is already enabled */ -    return; -  } -  msdp->flags |= PIM_MSDPF_ENABLE; -  msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); -  pim_msdp_sa_adv_timer_setup(true /* start */); -  /* setup sa cache based on local sources */ -  pim_msdp_sa_local_setup(); +	if (msdp->flags & PIM_MSDPF_ENABLE) { +		/* feature is already enabled */ +		return; +	} +	msdp->flags |= PIM_MSDPF_ENABLE; +	msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); +	pim_msdp_sa_adv_timer_setup(true /* start */); +	/* setup sa cache based on local sources */ +	pim_msdp_sa_local_setup();  }  /* MSDP init */ -void -pim_msdp_init(struct thread_master *master) +void pim_msdp_init(struct thread_master *master)  { -  msdp->master = master; +	msdp->master = master; -  msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, -                                 pim_msdp_peer_hash_eq, NULL); -  msdp->peer_list = list_new(); -  msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; -  msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; +	msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, +				      pim_msdp_peer_hash_eq, NULL); +	msdp->peer_list = list_new(); +	msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; +	msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; -  msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make, -                                 pim_msdp_sa_hash_eq, NULL); -  msdp->sa_list = list_new(); -  msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free; -  msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp; +	msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make, +				    pim_msdp_sa_hash_eq, NULL); +	msdp->sa_list = list_new(); +	msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free; +	msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp;  }  /* counterpart to MSDP init; XXX: unused currently */ -void -pim_msdp_exit(void) +void pim_msdp_exit(void)  { -  /* XXX: stop listener and delete all peer sessions */ +	/* XXX: stop listener and delete all peer sessions */ -  if (msdp->peer_hash) { -    hash_free(msdp->peer_hash); -    msdp->peer_hash = NULL; -  } +	if (msdp->peer_hash) { +		hash_free(msdp->peer_hash); +		msdp->peer_hash = NULL; +	} -  if (msdp->peer_list) { -    list_free(msdp->peer_list); -    msdp->peer_list = NULL; -  } +	if (msdp->peer_list) { +		list_free(msdp->peer_list); +		msdp->peer_list = NULL; +	}  } diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 308b437a63..66e5457df4 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -20,35 +20,35 @@  #define PIM_MSDP_H  enum pim_msdp_peer_state { -  PIM_MSDP_DISABLED, -  PIM_MSDP_INACTIVE, -  PIM_MSDP_LISTEN, -  PIM_MSDP_CONNECTING, -  PIM_MSDP_ESTABLISHED +	PIM_MSDP_DISABLED, +	PIM_MSDP_INACTIVE, +	PIM_MSDP_LISTEN, +	PIM_MSDP_CONNECTING, +	PIM_MSDP_ESTABLISHED  };  /* SA and KA TLVs are processed; rest ignored */  enum pim_msdp_tlv { -  PIM_MSDP_V4_SOURCE_ACTIVE = 1, -  PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, -  PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, -  PIM_MSDP_KEEPALIVE, -  PIM_MSDP_RESERVED, -  PIM_MSDP_TRACEROUTE_PROGRESS, -  PIM_MSDP_TRACEROUTE_REPLY, +	PIM_MSDP_V4_SOURCE_ACTIVE = 1, +	PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, +	PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, +	PIM_MSDP_KEEPALIVE, +	PIM_MSDP_RESERVED, +	PIM_MSDP_TRACEROUTE_PROGRESS, +	PIM_MSDP_TRACEROUTE_REPLY,  };  /* MSDP error codes */  enum pim_msdp_err { -  PIM_MSDP_ERR_NONE = 0, -  PIM_MSDP_ERR_OOM = -1, -  PIM_MSDP_ERR_PEER_EXISTS = -2, -  PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, -  PIM_MSDP_ERR_NO_PEER = -4, -  PIM_MSDP_ERR_MG_MBR_EXISTS = -5, -  PIM_MSDP_ERR_NO_MG = -6, -  PIM_MSDP_ERR_NO_MG_MBR = -7, -  PIM_MSDP_ERR_SIP_EQ_DIP = -8, +	PIM_MSDP_ERR_NONE = 0, +	PIM_MSDP_ERR_OOM = -1, +	PIM_MSDP_ERR_PEER_EXISTS = -2, +	PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, +	PIM_MSDP_ERR_NO_PEER = -4, +	PIM_MSDP_ERR_MG_MBR_EXISTS = -5, +	PIM_MSDP_ERR_NO_MG = -6, +	PIM_MSDP_ERR_NO_MG_MBR = -7, +	PIM_MSDP_ERR_SIP_EQ_DIP = -8,  };  #define PIM_MSDP_STATE_STRLEN 16 @@ -58,149 +58,155 @@ enum pim_msdp_err {  #define PIM_MSDP_SOCKET_SNDBUF_SIZE 65536  enum pim_msdp_sa_flags { -  PIM_MSDP_SAF_NONE = 0, -  /* There are two cases where we can pickup an active source locally - -   * 1. We are RP and got a source-register from the FHR -   * 2. We are RP and FHR and learnt a new directly connected source on a -   * DR interface */ -  PIM_MSDP_SAF_LOCAL = (1 << 0), -  /* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF -   * checks) */ -  PIM_MSDP_SAF_PEER = (1 << 1), -  PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), -  PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on -                                 * misc pim events such as RP change */ -  PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) +	PIM_MSDP_SAF_NONE = 0, +	/* There are two cases where we can pickup an active source locally - +	 * 1. We are RP and got a source-register from the FHR +	 * 2. We are RP and FHR and learnt a new directly connected source on a +	 * DR interface */ +	PIM_MSDP_SAF_LOCAL = (1 << 0), +	/* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF +	 * checks) */ +	PIM_MSDP_SAF_PEER = (1 << 1), +	PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), +	PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on +				       * misc pim events such as RP change */ +	PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3)  };  struct pim_msdp_sa { -  struct prefix_sg sg; -  char sg_str[PIM_SG_LEN]; -  struct in_addr rp; /* Last RP address associated with this SA */ -  struct in_addr peer; /* last peer from who we heard this SA */ -  enum pim_msdp_sa_flags flags; - -  /* rfc-3618 is missing default value for SA-hold-down-Period. pulled -   * this number from industry-standards */ +	struct prefix_sg sg; +	char sg_str[PIM_SG_LEN]; +	struct in_addr rp;   /* Last RP address associated with this SA */ +	struct in_addr peer; /* last peer from who we heard this SA */ +	enum pim_msdp_sa_flags flags; + +/* rfc-3618 is missing default value for SA-hold-down-Period. pulled + * this number from industry-standards */  #define PIM_MSDP_SA_HOLD_TIME ((3*60)+30) -  struct thread *sa_state_timer;  // 5.6 -  int64_t uptime; +	struct thread *sa_state_timer; // 5.6 +	int64_t uptime; -  struct pim_upstream *up; +	struct pim_upstream *up;  };  enum pim_msdp_peer_flags { -  PIM_MSDP_PEERF_NONE = 0, -  PIM_MSDP_PEERF_LISTENER = (1 << 0), +	PIM_MSDP_PEERF_NONE = 0, +	PIM_MSDP_PEERF_LISTENER = (1 << 0),  #define PIM_MSDP_PEER_IS_LISTENER(mp) (mp->flags & PIM_MSDP_PEERF_LISTENER) -  PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1) +	PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1)  };  struct pim_msdp_peer { -  /* configuration */ -  struct in_addr local; -  struct in_addr peer; -  char *mesh_group_name; -  char key_str[INET_ADDRSTRLEN]; - -  /* state */ -  enum pim_msdp_peer_state state; -  enum pim_msdp_peer_flags flags; - -  /* TCP socket info */ -  union sockunion su_local; -  union sockunion su_peer; -  int fd; - -  /* protocol timers */ +	/* configuration */ +	struct in_addr local; +	struct in_addr peer; +	char *mesh_group_name; +	char key_str[INET_ADDRSTRLEN]; + +	/* state */ +	enum pim_msdp_peer_state state; +	enum pim_msdp_peer_flags flags; + +	/* TCP socket info */ +	union sockunion su_local; +	union sockunion su_peer; +	int fd; + +/* protocol timers */  #define PIM_MSDP_PEER_HOLD_TIME 75 -  struct thread *hold_timer;   // 5.4 +	struct thread *hold_timer; // 5.4 +				   /* $FRR indent$ */ +/* clang-format off */  #define PIM_MSDP_PEER_KA_TIME 60 -  struct thread *ka_timer;  // 5.5 +	struct thread *ka_timer; // 5.5 +				 /* $FRR indent$ */ +				 /* clang-format off */  #define PIM_MSDP_PEER_CONNECT_RETRY_TIME 30 -  struct thread *cr_timer;  // 5.6 - -  /* packet thread and buffers */ -  uint32_t packet_size; -  struct stream *ibuf; -  struct stream_fifo *obuf; -  struct thread *t_read; -  struct thread *t_write; - -  /* stats */ -  uint32_t conn_attempts; -  uint32_t est_flaps; -  uint32_t sa_cnt; /* number of SAs attributed to this peer */ +	struct thread *cr_timer; // 5.6 + +	/* packet thread and buffers */ +	uint32_t packet_size; +	struct stream *ibuf; +	struct stream_fifo *obuf; +	struct thread *t_read; +	struct thread *t_write; + +	/* stats */ +	uint32_t conn_attempts; +	uint32_t est_flaps; +	uint32_t sa_cnt; /* number of SAs attributed to this peer */ +			 /* $FRR indent$ */ +			 /* clang-format off */  #define PIM_MSDP_PEER_LAST_RESET_STR 20 -  char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; +	char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; -  /* packet stats */ -  uint32_t ka_tx_cnt; -  uint32_t sa_tx_cnt; -  uint32_t ka_rx_cnt; -  uint32_t sa_rx_cnt; -  uint32_t unk_rx_cnt; +	/* packet stats */ +	uint32_t ka_tx_cnt; +	uint32_t sa_tx_cnt; +	uint32_t ka_rx_cnt; +	uint32_t sa_rx_cnt; +	uint32_t unk_rx_cnt; -  /* timestamps */ -  int64_t uptime; +	/* timestamps */ +	int64_t uptime;  };  struct pim_msdp_mg_mbr { -  struct in_addr mbr_ip; -  struct pim_msdp_peer *mp; +	struct in_addr mbr_ip; +	struct pim_msdp_peer *mp;  };  /* PIM MSDP mesh-group */  struct pim_msdp_mg { -  char *mesh_group_name; -  struct in_addr src_ip; -  uint32_t mbr_cnt; -  struct list *mbr_list; +	char *mesh_group_name; +	struct in_addr src_ip; +	uint32_t mbr_cnt; +	struct list *mbr_list;  };  enum pim_msdp_flags { -  PIM_MSDPF_NONE = 0, -  PIM_MSDPF_ENABLE = (1 << 0), -  PIM_MSDPF_LISTENER = (1 << 1) +	PIM_MSDPF_NONE = 0, +	PIM_MSDPF_ENABLE = (1 << 0), +	PIM_MSDPF_LISTENER = (1 << 1)  };  struct pim_msdp_listener { -  int fd; -  union sockunion su; -  struct thread *thread; +	int fd; +	union sockunion su; +	struct thread *thread;  };  struct pim_msdp { -  enum pim_msdp_flags flags; -  struct thread_master *master; -  struct pim_msdp_listener listener; -  uint32_t rejected_accepts; +	enum pim_msdp_flags flags; +	struct thread_master *master; +	struct pim_msdp_listener listener; +	uint32_t rejected_accepts; -  /* MSDP peer info */ -  struct hash *peer_hash; -  struct list *peer_list; +	/* MSDP peer info */ +	struct hash *peer_hash; +	struct list *peer_list; -  /* MSDP active-source info */ +/* MSDP active-source info */  #define PIM_MSDP_SA_ADVERTISMENT_TIME 60 -  struct thread *sa_adv_timer;  // 5.6 -  struct hash *sa_hash; -  struct list *sa_list; -  uint32_t local_cnt; +	struct thread *sa_adv_timer; // 5.6 +	struct hash *sa_hash; +	struct list *sa_list; +	uint32_t local_cnt; -  /* keep a scratch pad for building SA TLVs */ -  struct stream *work_obuf; +	/* keep a scratch pad for building SA TLVs */ +	struct stream *work_obuf; -  struct in_addr originator_id; +	struct in_addr originator_id; -  /* currently only one mesh-group is supported - so just stash it here */ -  struct pim_msdp_mg *mg; +	/* currently only one mesh-group is supported - so just stash it here */ +	struct pim_msdp_mg *mg;  }; -#define PIM_MSDP_PEER_READ_ON(mp) \ -  thread_add_read (msdp->master, pim_msdp_read, mp, mp->fd, &mp->t_read) +#define PIM_MSDP_PEER_READ_ON(mp)                                              \ +	thread_add_read(msdp->master, pim_msdp_read, mp, mp->fd, &mp->t_read) -#define PIM_MSDP_PEER_WRITE_ON(mp) \ -  thread_add_write (msdp->master, pim_msdp_write, mp, mp->fd, &mp->t_write) +#define PIM_MSDP_PEER_WRITE_ON(mp)                                             \ +	thread_add_write(msdp->master, pim_msdp_write, mp, mp->fd, &mp->t_write)  #define PIM_MSDP_PEER_READ_OFF(mp) THREAD_READ_OFF(mp->t_read)  #define PIM_MSDP_PEER_WRITE_OFF(mp) THREAD_WRITE_OFF(mp->t_write) @@ -208,28 +214,36 @@ struct pim_msdp {  extern struct pim_msdp *msdp;  void pim_msdp_init(struct thread_master *master);  void pim_msdp_exit(void); -enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, const char *mesh_group_name, struct pim_msdp_peer **mp_p); +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, +				    const char *mesh_group_name, +				    struct pim_msdp_peer **mp_p);  enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr); -char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size); +char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, +			  int buf_size);  struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr);  void pim_msdp_peer_established(struct pim_msdp_peer *mp);  void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp);  void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state);  void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str);  int pim_msdp_write(struct thread *thread); -char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format); +char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, +			     bool long_format);  int pim_msdp_config_write(struct vty *vty);  void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); -void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp); +void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, +		     struct in_addr rp);  void pim_msdp_sa_local_update(struct pim_upstream *up);  void pim_msdp_sa_local_del(struct prefix_sg *sg);  void pim_msdp_i_am_rp_changed(void);  bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp);  void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up);  void pim_msdp_up_del(struct prefix_sg *sg); -enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip); -enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, +				      struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, +				      struct in_addr mbr_ip);  enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name); -enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip); +enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, +				      struct in_addr src_ip);  enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name);  #endif diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 0a8679336a..01ce293e36 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -31,665 +31,661 @@  #include "pim_msdp_packet.h"  #include "pim_msdp_socket.h" -static char * -pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, int buf_size) +static char *pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, +				    int buf_size)  { -  switch (type) { -    case PIM_MSDP_V4_SOURCE_ACTIVE: -      snprintf(buf, buf_size, "%s", "SA"); -      break; -    case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST: -      snprintf(buf, buf_size, "%s", "SA_REQ"); -      break; -    case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE: -      snprintf(buf, buf_size, "%s", "SA_RESP"); -      break; -    case PIM_MSDP_KEEPALIVE: -      snprintf(buf, buf_size, "%s", "KA"); -      break; -    case PIM_MSDP_RESERVED: -      snprintf(buf, buf_size, "%s", "RSVD"); -      break; -    case PIM_MSDP_TRACEROUTE_PROGRESS: -      snprintf(buf, buf_size, "%s", "TRACE_PROG"); -      break; -    case PIM_MSDP_TRACEROUTE_REPLY: -      snprintf(buf, buf_size, "%s", "TRACE_REPLY"); -      break; -    default: -      snprintf(buf, buf_size, "UNK-%d", type); -  } -  return buf; +	switch (type) { +	case PIM_MSDP_V4_SOURCE_ACTIVE: +		snprintf(buf, buf_size, "%s", "SA"); +		break; +	case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST: +		snprintf(buf, buf_size, "%s", "SA_REQ"); +		break; +	case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE: +		snprintf(buf, buf_size, "%s", "SA_RESP"); +		break; +	case PIM_MSDP_KEEPALIVE: +		snprintf(buf, buf_size, "%s", "KA"); +		break; +	case PIM_MSDP_RESERVED: +		snprintf(buf, buf_size, "%s", "RSVD"); +		break; +	case PIM_MSDP_TRACEROUTE_PROGRESS: +		snprintf(buf, buf_size, "%s", "TRACE_PROG"); +		break; +	case PIM_MSDP_TRACEROUTE_REPLY: +		snprintf(buf, buf_size, "%s", "TRACE_REPLY"); +		break; +	default: +		snprintf(buf, buf_size, "UNK-%d", type); +	} +	return buf;  } -static void -pim_msdp_pkt_sa_dump_one(struct stream *s) +static void pim_msdp_pkt_sa_dump_one(struct stream *s)  { -  struct prefix_sg sg; +	struct prefix_sg sg; -  /* just throw away the three reserved bytes */ -  stream_get3(s); -  /* throw away the prefix length also */ -  stream_getc(s); +	/* just throw away the three reserved bytes */ +	stream_get3(s); +	/* throw away the prefix length also */ +	stream_getc(s); -  memset(&sg, 0, sizeof (struct prefix_sg)); -  sg.grp.s_addr = stream_get_ipv4(s); -  sg.src.s_addr = stream_get_ipv4(s); +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.grp.s_addr = stream_get_ipv4(s); +	sg.src.s_addr = stream_get_ipv4(s); -  zlog_debug("  sg %s", pim_str_sg_dump(&sg)); +	zlog_debug("  sg %s", pim_str_sg_dump(&sg));  } -static void -pim_msdp_pkt_sa_dump(struct stream *s) +static void pim_msdp_pkt_sa_dump(struct stream *s)  { -  int entry_cnt; -  int i; -  struct in_addr rp; /* Last RP address associated with this SA */ - -  entry_cnt = stream_getc(s); -  rp.s_addr = stream_get_ipv4(s); - -  if (PIM_DEBUG_MSDP_PACKETS) { -    char rp_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); -    zlog_debug("  entry_cnt %d rp %s", entry_cnt, rp_str); -  } - -  /* dump SAs */ -  for (i = 0; i < entry_cnt; ++i) { -    pim_msdp_pkt_sa_dump_one(s); -  } +	int entry_cnt; +	int i; +	struct in_addr rp; /* Last RP address associated with this SA */ + +	entry_cnt = stream_getc(s); +	rp.s_addr = stream_get_ipv4(s); + +	if (PIM_DEBUG_MSDP_PACKETS) { +		char rp_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); +		zlog_debug("  entry_cnt %d rp %s", entry_cnt, rp_str); +	} + +	/* dump SAs */ +	for (i = 0; i < entry_cnt; ++i) { +		pim_msdp_pkt_sa_dump_one(s); +	}  } -static void -pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, bool rx, -                  struct stream *s) +static void pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, +			      bool rx, struct stream *s)  { -  char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; +	char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; -  pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); +	pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); -  zlog_debug("MSDP peer %s pkt %s type %s len %d", -      mp->key_str, rx?"rx":"tx", type_str, len); +	zlog_debug("MSDP peer %s pkt %s type %s len %d", mp->key_str, +		   rx ? "rx" : "tx", type_str, len); -  if (!s) { -    return; -  } +	if (!s) { +		return; +	} -  switch(type) { -      case PIM_MSDP_V4_SOURCE_ACTIVE: -        pim_msdp_pkt_sa_dump(s); -        break; -      default:; -  } +	switch (type) { +	case PIM_MSDP_V4_SOURCE_ACTIVE: +		pim_msdp_pkt_sa_dump(s); +		break; +	default:; +	}  }  /* Check file descriptor whether connect is established. */ -static void -pim_msdp_connect_check(struct pim_msdp_peer *mp) +static void pim_msdp_connect_check(struct pim_msdp_peer *mp)  { -  int status; -  socklen_t slen; -  int ret; - -  if (mp->state != PIM_MSDP_CONNECTING) { -    /* if we are here it means we are not in a connecting or established state -     * for now treat this as a fatal error */ -    pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); -    return; -  } - -  PIM_MSDP_PEER_READ_OFF(mp); -  PIM_MSDP_PEER_WRITE_OFF(mp); - -  /* Check file descriptor. */ -  slen = sizeof(status); -  ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen); - -  /* If getsockopt is fail, this is fatal error. */ -  if (ret < 0) { -    zlog_err("can't get sockopt for nonblocking connect"); -    pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); -    return; -  } - -  /* When status is 0 then TCP connection is established. */ -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str, status?"fail":"success"); -  } -  if (status == 0) { -    pim_msdp_peer_established(mp); -  } else { -    pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); -  } +	int status; +	socklen_t slen; +	int ret; + +	if (mp->state != PIM_MSDP_CONNECTING) { +		/* if we are here it means we are not in a connecting or +		 * established state +		 * for now treat this as a fatal error */ +		pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); +		return; +	} + +	PIM_MSDP_PEER_READ_OFF(mp); +	PIM_MSDP_PEER_WRITE_OFF(mp); + +	/* Check file descriptor. */ +	slen = sizeof(status); +	ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen); + +	/* If getsockopt is fail, this is fatal error. */ +	if (ret < 0) { +		zlog_err("can't get sockopt for nonblocking connect"); +		pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); +		return; +	} + +	/* When status is 0 then TCP connection is established. */ +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str, +			   status ? "fail" : "success"); +	} +	if (status == 0) { +		pim_msdp_peer_established(mp); +	} else { +		pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); +	}  } -static void -pim_msdp_pkt_delete(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_delete(struct pim_msdp_peer *mp)  { -  stream_free(stream_fifo_pop(mp->obuf)); +	stream_free(stream_fifo_pop(mp->obuf));  } -static void -pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s) +static void pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s)  { -  stream_fifo_push(mp->obuf, s); +	stream_fifo_push(mp->obuf, s);  } -static void -pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp) +static void pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp)  { -  if (stream_fifo_head(mp->obuf)) { -    PIM_MSDP_PEER_WRITE_ON(mp); -  } +	if (stream_fifo_head(mp->obuf)) { +		PIM_MSDP_PEER_WRITE_ON(mp); +	}  } -int -pim_msdp_write(struct thread *thread) +int pim_msdp_write(struct thread *thread)  { -  struct pim_msdp_peer *mp; -  struct stream *s; -  int num; -  enum pim_msdp_tlv type; -  int len; -  int work_cnt = 0; -  int work_max_cnt = 100; - -  mp = THREAD_ARG(thread); -  mp->t_write = NULL; - -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str); -  } -  if (mp->fd < 0) { -    return -1; -  } - -  /* check if TCP connection is established */ -  if (mp->state != PIM_MSDP_ESTABLISHED) { -    pim_msdp_connect_check(mp); -    return 0; -  } - -  s = stream_fifo_head(mp->obuf); -  if (!s) { -    pim_msdp_write_proceed_actions(mp); -    return 0; -  } - -  sockopt_cork(mp->fd, 1); - -  /* Nonblocking write until TCP output buffer is full  */ -  do -  { -    int writenum; - -    /* Number of bytes to be sent */ -    writenum = stream_get_endp(s) - stream_get_getp(s); - -    /* Call write() system call */ -    num = write(mp->fd, STREAM_PNT(s), writenum); -    if (num < 0) { -      /* write failed either retry needed or error */ -      if (ERRNO_IO_RETRY(errno)) { -        if (PIM_DEBUG_MSDP_INTERNAL) { -          zlog_debug("MSDP peer %s pim_msdp_write io retry", mp->key_str); -        } -        break; -      } - -      pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); -      return 0; -    } - -    if (num != writenum) { -      /* Partial write */ -      stream_forward_getp(s, num); -      if (PIM_DEBUG_MSDP_INTERNAL) { -        zlog_debug("MSDP peer %s pim_msdp_partial_write", mp->key_str); -      } -      break; -    } - -    /* Retrieve msdp packet type. */ -    stream_set_getp(s,0); -    type = stream_getc(s); -    len = stream_getw(s); -    switch (type) -    { -      case PIM_MSDP_KEEPALIVE: -        mp->ka_tx_cnt++; -        break; -      case PIM_MSDP_V4_SOURCE_ACTIVE: -        mp->sa_tx_cnt++; -        break; -      default:; -    } -    if (PIM_DEBUG_MSDP_PACKETS) { -      pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s); -    } - -    /* packet sent delete it. */ -    pim_msdp_pkt_delete(mp); - -    ++work_cnt; -    /* may need to pause if we have done too much work in this -     * loop */ -    if (work_cnt >= work_max_cnt) { -      break; -    } -  } while ((s = stream_fifo_head(mp->obuf)) != NULL); -  pim_msdp_write_proceed_actions(mp); - -  sockopt_cork(mp->fd, 0); - -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets", mp->key_str, work_cnt); -  } - -  return 0; +	struct pim_msdp_peer *mp; +	struct stream *s; +	int num; +	enum pim_msdp_tlv type; +	int len; +	int work_cnt = 0; +	int work_max_cnt = 100; + +	mp = THREAD_ARG(thread); +	mp->t_write = NULL; + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str); +	} +	if (mp->fd < 0) { +		return -1; +	} + +	/* check if TCP connection is established */ +	if (mp->state != PIM_MSDP_ESTABLISHED) { +		pim_msdp_connect_check(mp); +		return 0; +	} + +	s = stream_fifo_head(mp->obuf); +	if (!s) { +		pim_msdp_write_proceed_actions(mp); +		return 0; +	} + +	sockopt_cork(mp->fd, 1); + +	/* Nonblocking write until TCP output buffer is full  */ +	do { +		int writenum; + +		/* Number of bytes to be sent */ +		writenum = stream_get_endp(s) - stream_get_getp(s); + +		/* Call write() system call */ +		num = write(mp->fd, STREAM_PNT(s), writenum); +		if (num < 0) { +			/* write failed either retry needed or error */ +			if (ERRNO_IO_RETRY(errno)) { +				if (PIM_DEBUG_MSDP_INTERNAL) { +					zlog_debug( +						"MSDP peer %s pim_msdp_write io retry", +						mp->key_str); +				} +				break; +			} + +			pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); +			return 0; +		} + +		if (num != writenum) { +			/* Partial write */ +			stream_forward_getp(s, num); +			if (PIM_DEBUG_MSDP_INTERNAL) { +				zlog_debug( +					"MSDP peer %s pim_msdp_partial_write", +					mp->key_str); +			} +			break; +		} + +		/* Retrieve msdp packet type. */ +		stream_set_getp(s, 0); +		type = stream_getc(s); +		len = stream_getw(s); +		switch (type) { +		case PIM_MSDP_KEEPALIVE: +			mp->ka_tx_cnt++; +			break; +		case PIM_MSDP_V4_SOURCE_ACTIVE: +			mp->sa_tx_cnt++; +			break; +		default:; +		} +		if (PIM_DEBUG_MSDP_PACKETS) { +			pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s); +		} + +		/* packet sent delete it. */ +		pim_msdp_pkt_delete(mp); + +		++work_cnt; +		/* may need to pause if we have done too much work in this +		 * loop */ +		if (work_cnt >= work_max_cnt) { +			break; +		} +	} while ((s = stream_fifo_head(mp->obuf)) != NULL); +	pim_msdp_write_proceed_actions(mp); + +	sockopt_cork(mp->fd, 0); + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets", +			   mp->key_str, work_cnt); +	} + +	return 0;  } -static void -pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s) +static void pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s)  { -  /* Add packet to the end of list. */ -  pim_msdp_pkt_add(mp, s); +	/* Add packet to the end of list. */ +	pim_msdp_pkt_add(mp, s); -  PIM_MSDP_PEER_WRITE_ON(mp); +	PIM_MSDP_PEER_WRITE_ON(mp);  } -void -pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) +void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp)  { -  struct stream *s; +	struct stream *s; -  if (mp->state != PIM_MSDP_ESTABLISHED) { -    /* don't tx anything unless a session is established */ -    return; -  } -  s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); -  stream_putc(s, PIM_MSDP_KEEPALIVE); -  stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); +	if (mp->state != PIM_MSDP_ESTABLISHED) { +		/* don't tx anything unless a session is established */ +		return; +	} +	s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); +	stream_putc(s, PIM_MSDP_KEEPALIVE); +	stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); -  pim_msdp_pkt_send(mp, s); +	pim_msdp_pkt_send(mp, s);  } -static void -pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp)  { -  struct stream *s; - -  if (mp->state != PIM_MSDP_ESTABLISHED) { -    /* don't tx anything unless a session is established */ -    return; -  } -  s = stream_dup(msdp->work_obuf); -  if (s) { -    pim_msdp_pkt_send(mp, s); -    mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT; -  } +	struct stream *s; + +	if (mp->state != PIM_MSDP_ESTABLISHED) { +		/* don't tx anything unless a session is established */ +		return; +	} +	s = stream_dup(msdp->work_obuf); +	if (s) { +		pim_msdp_pkt_send(mp, s); +		mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT; +	}  }  /* push the stream into the obuf fifo of all the peers */ -static void -pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp)  { -  struct listnode *mpnode; - -  if (mp) { -    pim_msdp_pkt_sa_push_to_one_peer(mp); -  } else { -    for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { -      if (PIM_DEBUG_MSDP_INTERNAL) { -        zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push", mp->key_str); -      } -      pim_msdp_pkt_sa_push_to_one_peer(mp); -    } -  } +	struct listnode *mpnode; + +	if (mp) { +		pim_msdp_pkt_sa_push_to_one_peer(mp); +	} else { +		for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { +			if (PIM_DEBUG_MSDP_INTERNAL) { +				zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push", +					   mp->key_str); +			} +			pim_msdp_pkt_sa_push_to_one_peer(mp); +		} +	}  } -static int -pim_msdp_pkt_sa_fill_hdr(int local_cnt) +static int pim_msdp_pkt_sa_fill_hdr(int local_cnt)  { -  int curr_tlv_ecnt; - -  stream_reset(msdp->work_obuf); -  curr_tlv_ecnt = local_cnt>PIM_MSDP_SA_MAX_ENTRY_CNT?PIM_MSDP_SA_MAX_ENTRY_CNT:local_cnt; -  local_cnt -= curr_tlv_ecnt; -  stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE); -  stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); -  stream_putc(msdp->work_obuf, curr_tlv_ecnt); -  stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr); - -  return local_cnt; +	int curr_tlv_ecnt; + +	stream_reset(msdp->work_obuf); +	curr_tlv_ecnt = local_cnt > PIM_MSDP_SA_MAX_ENTRY_CNT +				? PIM_MSDP_SA_MAX_ENTRY_CNT +				: local_cnt; +	local_cnt -= curr_tlv_ecnt; +	stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE); +	stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); +	stream_putc(msdp->work_obuf, curr_tlv_ecnt); +	stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr); + +	return local_cnt;  } -static void -pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa) +static void pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa)  { -  stream_put3(msdp->work_obuf, 0 /* reserved */); -  stream_putc(msdp->work_obuf, 32 /* sprefix len */); -  stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr); -  stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr); +	stream_put3(msdp->work_obuf, 0 /* reserved */); +	stream_putc(msdp->work_obuf, 32 /* sprefix len */); +	stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr); +	stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr);  } -static void -pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp)  { -  struct listnode *sanode; -  struct pim_msdp_sa *sa; -  int sa_count; -  int local_cnt = msdp->local_cnt; - -  sa_count = 0; -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("  sa gen  %d", local_cnt); -  } - -  local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); - -  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { -      /* current implementation of MSDP is for anycast i.e. full mesh. so -       * no re-forwarding of SAs that we learnt from other peers */ -      continue; -    } -    /* add sa into scratch pad */ -    pim_msdp_pkt_sa_fill_one(sa); -    ++sa_count; -    if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) { -      pim_msdp_pkt_sa_push(mp); -      /* reset headers */ -      sa_count = 0; -      if (PIM_DEBUG_MSDP_INTERNAL) { -          zlog_debug("  sa gen for remainder %d", local_cnt); -      } -      local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); -    } -  } - -  if (sa_count) { -    pim_msdp_pkt_sa_push(mp); -  } -  return; +	struct listnode *sanode; +	struct pim_msdp_sa *sa; +	int sa_count; +	int local_cnt = msdp->local_cnt; + +	sa_count = 0; +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("  sa gen  %d", local_cnt); +	} + +	local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); + +	for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +		if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { +			/* current implementation of MSDP is for anycast i.e. +			 * full mesh. so +			 * no re-forwarding of SAs that we learnt from other +			 * peers */ +			continue; +		} +		/* add sa into scratch pad */ +		pim_msdp_pkt_sa_fill_one(sa); +		++sa_count; +		if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) { +			pim_msdp_pkt_sa_push(mp); +			/* reset headers */ +			sa_count = 0; +			if (PIM_DEBUG_MSDP_INTERNAL) { +				zlog_debug("  sa gen for remainder %d", +					   local_cnt); +			} +			local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); +		} +	} + +	if (sa_count) { +		pim_msdp_pkt_sa_push(mp); +	} +	return;  } -static void -pim_msdp_pkt_sa_tx_done(void) +static void pim_msdp_pkt_sa_tx_done(void)  { -  struct listnode *mpnode; -  struct pim_msdp_peer *mp; - -  /* if SA were sent to the peers we restart ka timer and avoid -   * unnecessary ka noise */ -  for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { -    if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) { -      mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT; -      pim_msdp_peer_pkt_txed(mp); -    } -  } +	struct listnode *mpnode; +	struct pim_msdp_peer *mp; + +	/* if SA were sent to the peers we restart ka timer and avoid +	 * unnecessary ka noise */ +	for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { +		if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) { +			mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT; +			pim_msdp_peer_pkt_txed(mp); +		} +	}  } -void -pim_msdp_pkt_sa_tx(void) +void pim_msdp_pkt_sa_tx(void)  { -  pim_msdp_pkt_sa_gen(NULL /* mp */); -  pim_msdp_pkt_sa_tx_done(); +	pim_msdp_pkt_sa_gen(NULL /* mp */); +	pim_msdp_pkt_sa_tx_done();  } -void -pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa) +void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa)  { -  pim_msdp_pkt_sa_fill_hdr(1 /* cnt */); -  pim_msdp_pkt_sa_fill_one(sa); -  pim_msdp_pkt_sa_push(NULL); -  pim_msdp_pkt_sa_tx_done(); +	pim_msdp_pkt_sa_fill_hdr(1 /* cnt */); +	pim_msdp_pkt_sa_fill_one(sa); +	pim_msdp_pkt_sa_push(NULL); +	pim_msdp_pkt_sa_tx_done();  }  /* when a connection is first established we push all SAs immediately */ -void -pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) +void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp)  { -  pim_msdp_pkt_sa_gen(mp); -  pim_msdp_pkt_sa_tx_done(); +	pim_msdp_pkt_sa_gen(mp); +	pim_msdp_pkt_sa_tx_done();  } -static void -pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp)  { -  pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); +	pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx");  } -static void -pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len) +static void pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len)  { -  mp->ka_rx_cnt++; -  if (len !=  PIM_MSDP_KA_TLV_MAX_SIZE) { -    pim_msdp_pkt_rxed_with_fatal_error(mp); -    return; -  } -  pim_msdp_peer_pkt_rxed(mp); +	mp->ka_rx_cnt++; +	if (len != PIM_MSDP_KA_TLV_MAX_SIZE) { +		pim_msdp_pkt_rxed_with_fatal_error(mp); +		return; +	} +	pim_msdp_peer_pkt_rxed(mp);  } -static void -pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) +static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp)  { -  int prefix_len; -  struct prefix_sg sg; - -  /* just throw away the three reserved bytes */ -  stream_get3(mp->ibuf); -  prefix_len = stream_getc(mp->ibuf); - -  memset(&sg, 0, sizeof (struct prefix_sg)); -  sg.grp.s_addr = stream_get_ipv4(mp->ibuf); -  sg.src.s_addr = stream_get_ipv4(mp->ibuf); - -  if (prefix_len != 32) { -    /* ignore SA update if the prefix length is not 32 */ -    zlog_err("rxed sa update with invalid prefix length %d", prefix_len); -    return; -  } -  if (PIM_DEBUG_MSDP_PACKETS) { -    zlog_debug("  sg %s", pim_str_sg_dump(&sg)); -  } -  pim_msdp_sa_ref(mp, &sg, rp); +	int prefix_len; +	struct prefix_sg sg; + +	/* just throw away the three reserved bytes */ +	stream_get3(mp->ibuf); +	prefix_len = stream_getc(mp->ibuf); + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.grp.s_addr = stream_get_ipv4(mp->ibuf); +	sg.src.s_addr = stream_get_ipv4(mp->ibuf); + +	if (prefix_len != 32) { +		/* ignore SA update if the prefix length is not 32 */ +		zlog_err("rxed sa update with invalid prefix length %d", +			 prefix_len); +		return; +	} +	if (PIM_DEBUG_MSDP_PACKETS) { +		zlog_debug("  sg %s", pim_str_sg_dump(&sg)); +	} +	pim_msdp_sa_ref(mp, &sg, rp);  } -static void -pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) +static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len)  { -  int entry_cnt; -  int i; -  struct in_addr rp; /* Last RP address associated with this SA */ - -  mp->sa_rx_cnt++; - -  if (len <  PIM_MSDP_SA_TLV_MIN_SIZE) { -    pim_msdp_pkt_rxed_with_fatal_error(mp); -    return; -  } - -  entry_cnt = stream_getc(mp->ibuf); -  /* some vendors include the actual multicast data in the tlv (at the end). -   * we will ignore such data. in the future we may consider pushing it down -   * the RPT */ -  if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) { -    pim_msdp_pkt_rxed_with_fatal_error(mp); -    return; -  } -  rp.s_addr = stream_get_ipv4(mp->ibuf); - -  if (PIM_DEBUG_MSDP_PACKETS) { -    char rp_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); -    zlog_debug("  entry_cnt %d rp %s", entry_cnt, rp_str); -  } - -  if (!pim_msdp_peer_rpf_check(mp, rp)) { -    /* if peer-RPF check fails don't process the packet any further */ -    if (PIM_DEBUG_MSDP_PACKETS) { -      zlog_debug("  peer RPF check failed"); -    } -    return; -  } - -  pim_msdp_peer_pkt_rxed(mp); - -  /* update SA cache */ -  for (i = 0; i < entry_cnt; ++i) { -    pim_msdp_pkt_sa_rx_one(mp, rp); -  } +	int entry_cnt; +	int i; +	struct in_addr rp; /* Last RP address associated with this SA */ + +	mp->sa_rx_cnt++; + +	if (len < PIM_MSDP_SA_TLV_MIN_SIZE) { +		pim_msdp_pkt_rxed_with_fatal_error(mp); +		return; +	} + +	entry_cnt = stream_getc(mp->ibuf); +	/* some vendors include the actual multicast data in the tlv (at the +	 * end). +	 * we will ignore such data. in the future we may consider pushing it +	 * down +	 * the RPT */ +	if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) { +		pim_msdp_pkt_rxed_with_fatal_error(mp); +		return; +	} +	rp.s_addr = stream_get_ipv4(mp->ibuf); + +	if (PIM_DEBUG_MSDP_PACKETS) { +		char rp_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<rp?>", rp, rp_str, sizeof(rp_str)); +		zlog_debug("  entry_cnt %d rp %s", entry_cnt, rp_str); +	} + +	if (!pim_msdp_peer_rpf_check(mp, rp)) { +		/* if peer-RPF check fails don't process the packet any further +		 */ +		if (PIM_DEBUG_MSDP_PACKETS) { +			zlog_debug("  peer RPF check failed"); +		} +		return; +	} + +	pim_msdp_peer_pkt_rxed(mp); + +	/* update SA cache */ +	for (i = 0; i < entry_cnt; ++i) { +		pim_msdp_pkt_sa_rx_one(mp, rp); +	}  } -static void -pim_msdp_pkt_rx(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_rx(struct pim_msdp_peer *mp)  { -  enum pim_msdp_tlv type; -  int len; - -  /* re-read type and len */ -  type = stream_getc_from(mp->ibuf, 0); -  len = stream_getw_from(mp->ibuf, 1); -  if (len <  PIM_MSDP_HEADER_SIZE) { -    pim_msdp_pkt_rxed_with_fatal_error(mp); -    return; -  } - -  if (len > PIM_MSDP_SA_TLV_MAX_SIZE) { -    /* if tlv size if greater than max just ignore the tlv */ -    return; -  } - -  if (PIM_DEBUG_MSDP_PACKETS) { -    pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/); -  } - -  switch(type) { -      case PIM_MSDP_KEEPALIVE: -        pim_msdp_pkt_ka_rx(mp, len); -        break; -      case PIM_MSDP_V4_SOURCE_ACTIVE: -        mp->sa_rx_cnt++; -        pim_msdp_pkt_sa_rx(mp, len); -        break; -      default: -        mp->unk_rx_cnt++; -  } +	enum pim_msdp_tlv type; +	int len; + +	/* re-read type and len */ +	type = stream_getc_from(mp->ibuf, 0); +	len = stream_getw_from(mp->ibuf, 1); +	if (len < PIM_MSDP_HEADER_SIZE) { +		pim_msdp_pkt_rxed_with_fatal_error(mp); +		return; +	} + +	if (len > PIM_MSDP_SA_TLV_MAX_SIZE) { +		/* if tlv size if greater than max just ignore the tlv */ +		return; +	} + +	if (PIM_DEBUG_MSDP_PACKETS) { +		pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/); +	} + +	switch (type) { +	case PIM_MSDP_KEEPALIVE: +		pim_msdp_pkt_ka_rx(mp, len); +		break; +	case PIM_MSDP_V4_SOURCE_ACTIVE: +		mp->sa_rx_cnt++; +		pim_msdp_pkt_sa_rx(mp, len); +		break; +	default: +		mp->unk_rx_cnt++; +	}  }  /* pim msdp read utility function. */ -static int -pim_msdp_read_packet(struct pim_msdp_peer *mp) +static int pim_msdp_read_packet(struct pim_msdp_peer *mp)  { -  int nbytes; -  int readsize; -  int old_endp; -  int new_endp; - -  old_endp = stream_get_endp(mp->ibuf); -  readsize = mp->packet_size - old_endp; -  if (!readsize) { -    return 0; -  } - -  /* Read packet from fd */ -  nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); -  new_endp = stream_get_endp(mp->ibuf); -  if (nbytes < 0) { -    if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); -    } -    if (nbytes == -2) { -      if (PIM_DEBUG_MSDP_INTERNAL) { -        zlog_debug("MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d", mp->key_str, old_endp, new_endp); -      } -      /* transient error retry */ -      return -1; -    } -    pim_msdp_pkt_rxed_with_fatal_error(mp); -    return -1; -  } - -  if (!nbytes) { -    if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); -    } -    pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); -    return -1; -  } - -  /* We read partial packet. */ -  if (stream_get_endp(mp->ibuf) != mp->packet_size) { -    if (PIM_DEBUG_MSDP_INTERNAL) { -      zlog_debug("MSDP peer %s read partial len %d old_endp %d new_endp %d", mp->key_str, mp->packet_size, old_endp, new_endp); -    } -    return -1; -  } - -  return 0; +	int nbytes; +	int readsize; +	int old_endp; +	int new_endp; + +	old_endp = stream_get_endp(mp->ibuf); +	readsize = mp->packet_size - old_endp; +	if (!readsize) { +		return 0; +	} + +	/* Read packet from fd */ +	nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); +	new_endp = stream_get_endp(mp->ibuf); +	if (nbytes < 0) { +		if (PIM_DEBUG_MSDP_INTERNAL) { +			zlog_debug("MSDP peer %s read failed %d", mp->key_str, +				   nbytes); +		} +		if (nbytes == -2) { +			if (PIM_DEBUG_MSDP_INTERNAL) { +				zlog_debug( +					"MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d", +					mp->key_str, old_endp, new_endp); +			} +			/* transient error retry */ +			return -1; +		} +		pim_msdp_pkt_rxed_with_fatal_error(mp); +		return -1; +	} + +	if (!nbytes) { +		if (PIM_DEBUG_MSDP_INTERNAL) { +			zlog_debug("MSDP peer %s read failed %d", mp->key_str, +				   nbytes); +		} +		pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); +		return -1; +	} + +	/* We read partial packet. */ +	if (stream_get_endp(mp->ibuf) != mp->packet_size) { +		if (PIM_DEBUG_MSDP_INTERNAL) { +			zlog_debug( +				"MSDP peer %s read partial len %d old_endp %d new_endp %d", +				mp->key_str, mp->packet_size, old_endp, +				new_endp); +		} +		return -1; +	} + +	return 0;  } -int -pim_msdp_read(struct thread *thread) +int pim_msdp_read(struct thread *thread)  { -  struct pim_msdp_peer *mp; -  int rc; -  uint32_t len; - -  mp = THREAD_ARG(thread); -  mp->t_read = NULL; - -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str); -  } - -  if (mp->fd < 0) { -    return -1; -  } - -  /* check if TCP connection is established */ -  if (mp->state != PIM_MSDP_ESTABLISHED) { -    pim_msdp_connect_check(mp); -    return 0; -  } - -  PIM_MSDP_PEER_READ_ON(mp); - -  if (!mp->packet_size) { -    mp->packet_size = PIM_MSDP_HEADER_SIZE; -  } - -  if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) { -    /* start by reading the TLV header */ -    rc = pim_msdp_read_packet(mp); -    if (rc < 0) { -      goto pim_msdp_read_end; -    } - -    /* Find TLV type and len  */ -    stream_getc(mp->ibuf); -    len = stream_getw(mp->ibuf); -    if (len < PIM_MSDP_HEADER_SIZE) { -      pim_msdp_pkt_rxed_with_fatal_error(mp); -      goto pim_msdp_read_end; -    } -    /* read complete TLV */ -    mp->packet_size = len; -  } - -  rc = pim_msdp_read_packet(mp); -  if (rc < 0) { -    goto pim_msdp_read_end; -  } - -  pim_msdp_pkt_rx(mp); - -  /* reset input buffers and get ready for the next packet */ -  mp->packet_size = 0; -  stream_reset(mp->ibuf); +	struct pim_msdp_peer *mp; +	int rc; +	uint32_t len; + +	mp = THREAD_ARG(thread); +	mp->t_read = NULL; + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str); +	} + +	if (mp->fd < 0) { +		return -1; +	} + +	/* check if TCP connection is established */ +	if (mp->state != PIM_MSDP_ESTABLISHED) { +		pim_msdp_connect_check(mp); +		return 0; +	} + +	PIM_MSDP_PEER_READ_ON(mp); + +	if (!mp->packet_size) { +		mp->packet_size = PIM_MSDP_HEADER_SIZE; +	} + +	if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) { +		/* start by reading the TLV header */ +		rc = pim_msdp_read_packet(mp); +		if (rc < 0) { +			goto pim_msdp_read_end; +		} + +		/* Find TLV type and len  */ +		stream_getc(mp->ibuf); +		len = stream_getw(mp->ibuf); +		if (len < PIM_MSDP_HEADER_SIZE) { +			pim_msdp_pkt_rxed_with_fatal_error(mp); +			goto pim_msdp_read_end; +		} +		/* read complete TLV */ +		mp->packet_size = len; +	} + +	rc = pim_msdp_read_packet(mp); +	if (rc < 0) { +		goto pim_msdp_read_end; +	} + +	pim_msdp_pkt_rx(mp); + +	/* reset input buffers and get ready for the next packet */ +	mp->packet_size = 0; +	stream_reset(mp->ibuf);  pim_msdp_read_end: -  return 0; +	return 0;  } diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h index aa42bbfe4b..986fa3b32a 100644 --- a/pimd/pim_msdp_packet.h +++ b/pimd/pim_msdp_packet.h @@ -50,8 +50,8 @@  #define PIM_MSDP_SA_X_SIZE 8  #define PIM_MSDP_SA_ONE_ENTRY_SIZE 12  #define PIM_MSDP_SA_Y_SIZE(entry_cnt) (PIM_MSDP_SA_ONE_ENTRY_SIZE * entry_cnt) -#define PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt) (PIM_MSDP_SA_X_SIZE +\ -                                    PIM_MSDP_SA_Y_SIZE(entry_cnt)) +#define PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)                                  \ +	(PIM_MSDP_SA_X_SIZE + PIM_MSDP_SA_Y_SIZE(entry_cnt))  /* SA TLV has to have atleast only one entry in it so x=8 + y=12 */  #define PIM_MSDP_SA_TLV_MIN_SIZE PIM_MSDP_SA_ENTRY_CNT2SIZE(1)  /* XXX: theoretically we can fix a max of 255 but that may result in packet diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index 9662f054e8..0ce0971012 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -31,199 +31,207 @@  #include "pim_msdp_socket.h"  /* increase socket send buffer size */ -static void -pim_msdp_update_sock_send_buffer_size (int fd) +static void pim_msdp_update_sock_send_buffer_size(int fd)  { -  int size = PIM_MSDP_SOCKET_SNDBUF_SIZE; -  int optval; -  socklen_t optlen = sizeof(optval); - -  if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { -    zlog_err("getsockopt of SO_SNDBUF failed %s\n", safe_strerror(errno)); -    return; -  } - -  if (optval < size) { -    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0) { -      zlog_err("Couldn't increase send buffer: %s\n", safe_strerror(errno)); -    } -  } +	int size = PIM_MSDP_SOCKET_SNDBUF_SIZE; +	int optval; +	socklen_t optlen = sizeof(optval); + +	if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { +		zlog_err("getsockopt of SO_SNDBUF failed %s\n", +			 safe_strerror(errno)); +		return; +	} + +	if (optval < size) { +		if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) +		    < 0) { +			zlog_err("Couldn't increase send buffer: %s\n", +				 safe_strerror(errno)); +		} +	}  }  /* passive peer socket accept */ -static int -pim_msdp_sock_accept(struct thread *thread) +static int pim_msdp_sock_accept(struct thread *thread)  { -  union sockunion su; -  struct pim_msdp_listener *listener = THREAD_ARG(thread); -  int accept_sock; -  int msdp_sock; -  struct pim_msdp_peer *mp; -  char buf[SU_ADDRSTRLEN]; - -  sockunion_init(&su); - -  /* re-register accept thread */ -  accept_sock = THREAD_FD(thread); -  if (accept_sock < 0) { -    zlog_err ("accept_sock is negative value %d", accept_sock); -    return -1; -  } -  listener->thread = NULL; -  thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock, -                  &listener->thread); - -  /* accept client connection. */ -  msdp_sock = sockunion_accept(accept_sock, &su); -  if (msdp_sock < 0) { -    zlog_err ("pim_msdp_sock_accept failed (%s)", safe_strerror (errno)); -    return -1; -  } - -  /* see if have peer config for this */ -  mp = pim_msdp_peer_find(su.sin.sin_addr); -  if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { -    ++msdp->rejected_accepts; -    if (PIM_DEBUG_MSDP_EVENTS) { -      zlog_err("msdp peer connection refused from %s", -          sockunion2str(&su, buf, SU_ADDRSTRLEN)); -    } -    close(msdp_sock); -    return -1; -  } - -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s accept success%s", mp->key_str, mp->fd>=0?"(dup)":""); -  } - -  /* if we have an existing connection we need to kill that one -   * with this one */ -  if (mp->fd >= 0) { -    if (PIM_DEBUG_MSDP_EVENTS) { -      zlog_err("msdp peer new connection from %s stop old connection", -          sockunion2str(&su, buf, SU_ADDRSTRLEN)); -    } -    pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); -  } -  mp->fd = msdp_sock; -  set_nonblocking(mp->fd); -  pim_msdp_update_sock_send_buffer_size(mp->fd); -  pim_msdp_peer_established(mp); -  return 0; +	union sockunion su; +	struct pim_msdp_listener *listener = THREAD_ARG(thread); +	int accept_sock; +	int msdp_sock; +	struct pim_msdp_peer *mp; +	char buf[SU_ADDRSTRLEN]; + +	sockunion_init(&su); + +	/* re-register accept thread */ +	accept_sock = THREAD_FD(thread); +	if (accept_sock < 0) { +		zlog_err("accept_sock is negative value %d", accept_sock); +		return -1; +	} +	listener->thread = NULL; +	thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock, +			&listener->thread); + +	/* accept client connection. */ +	msdp_sock = sockunion_accept(accept_sock, &su); +	if (msdp_sock < 0) { +		zlog_err("pim_msdp_sock_accept failed (%s)", +			 safe_strerror(errno)); +		return -1; +	} + +	/* see if have peer config for this */ +	mp = pim_msdp_peer_find(su.sin.sin_addr); +	if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { +		++msdp->rejected_accepts; +		if (PIM_DEBUG_MSDP_EVENTS) { +			zlog_err("msdp peer connection refused from %s", +				 sockunion2str(&su, buf, SU_ADDRSTRLEN)); +		} +		close(msdp_sock); +		return -1; +	} + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s accept success%s", mp->key_str, +			   mp->fd >= 0 ? "(dup)" : ""); +	} + +	/* if we have an existing connection we need to kill that one +	 * with this one */ +	if (mp->fd >= 0) { +		if (PIM_DEBUG_MSDP_EVENTS) { +			zlog_err( +				"msdp peer new connection from %s stop old connection", +				sockunion2str(&su, buf, SU_ADDRSTRLEN)); +		} +		pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); +	} +	mp->fd = msdp_sock; +	set_nonblocking(mp->fd); +	pim_msdp_update_sock_send_buffer_size(mp->fd); +	pim_msdp_peer_established(mp); +	return 0;  }  /* global listener for the MSDP well know TCP port */ -int -pim_msdp_sock_listen(void) +int pim_msdp_sock_listen(void)  { -  int sock; -  int socklen; -  struct sockaddr_in sin; -  int rc; -  struct pim_msdp_listener *listener = &msdp->listener; - -  if (msdp->flags & PIM_MSDPF_LISTENER) { -    /* listener already setup */ -    return 0; -  } - -  sock = socket(AF_INET, SOCK_STREAM, 0); -  if (sock < 0) { -    zlog_err ("socket: %s", safe_strerror (errno)); -    return sock; -  } - -  memset(&sin, 0, sizeof(struct sockaddr_in)); -  sin.sin_family = AF_INET; -  sin.sin_port = htons(PIM_MSDP_TCP_PORT); -  socklen = sizeof(struct sockaddr_in); +	int sock; +	int socklen; +	struct sockaddr_in sin; +	int rc; +	struct pim_msdp_listener *listener = &msdp->listener; + +	if (msdp->flags & PIM_MSDPF_LISTENER) { +		/* listener already setup */ +		return 0; +	} + +	sock = socket(AF_INET, SOCK_STREAM, 0); +	if (sock < 0) { +		zlog_err("socket: %s", safe_strerror(errno)); +		return sock; +	} + +	memset(&sin, 0, sizeof(struct sockaddr_in)); +	sin.sin_family = AF_INET; +	sin.sin_port = htons(PIM_MSDP_TCP_PORT); +	socklen = sizeof(struct sockaddr_in);  #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN -  sin.sin_len = socklen; +	sin.sin_len = socklen;  #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ -  sockopt_reuseaddr(sock); -  sockopt_reuseport(sock); - -  if (pimd_privs.change(ZPRIVS_RAISE)) { -    zlog_err ("pim_msdp_socket: could not raise privs, %s", -        safe_strerror (errno)); -  } - -  /* bind to well known TCP port */ -  rc = bind(sock, (struct sockaddr *)&sin, socklen); - -  if (pimd_privs.change(ZPRIVS_LOWER)) { -    zlog_err ("pim_msdp_socket: could not lower privs, %s", -        safe_strerror (errno)); -  } - -  if (rc < 0) { -    zlog_err ("pim_msdp_socket bind to port %d: %s", ntohs(sin.sin_port), safe_strerror (errno)); -    close(sock); -    return rc; -  } - -  rc = listen(sock, 3 /* backlog */); -  if (rc < 0) { -    zlog_err ("pim_msdp_socket listen: %s", safe_strerror (errno)); -    close(sock); -    return rc; -  } - -  /* add accept thread */ -  listener->fd = sock; -  memcpy(&listener->su, &sin, socklen); -  listener->thread = NULL; -  thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock, -                  &listener->thread); - -  msdp->flags |= PIM_MSDPF_LISTENER; -  return 0; +	sockopt_reuseaddr(sock); +	sockopt_reuseport(sock); + +	if (pimd_privs.change(ZPRIVS_RAISE)) { +		zlog_err("pim_msdp_socket: could not raise privs, %s", +			 safe_strerror(errno)); +	} + +	/* bind to well known TCP port */ +	rc = bind(sock, (struct sockaddr *)&sin, socklen); + +	if (pimd_privs.change(ZPRIVS_LOWER)) { +		zlog_err("pim_msdp_socket: could not lower privs, %s", +			 safe_strerror(errno)); +	} + +	if (rc < 0) { +		zlog_err("pim_msdp_socket bind to port %d: %s", +			 ntohs(sin.sin_port), safe_strerror(errno)); +		close(sock); +		return rc; +	} + +	rc = listen(sock, 3 /* backlog */); +	if (rc < 0) { +		zlog_err("pim_msdp_socket listen: %s", safe_strerror(errno)); +		close(sock); +		return rc; +	} + +	/* add accept thread */ +	listener->fd = sock; +	memcpy(&listener->su, &sin, socklen); +	listener->thread = NULL; +	thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock, +			&listener->thread); + +	msdp->flags |= PIM_MSDPF_LISTENER; +	return 0;  }  /* active peer socket setup */ -int -pim_msdp_sock_connect(struct pim_msdp_peer *mp) +int pim_msdp_sock_connect(struct pim_msdp_peer *mp)  { -  int rc; - -  if (PIM_DEBUG_MSDP_INTERNAL) { -    zlog_debug("MSDP peer %s attempt connect%s", mp->key_str, mp->fd<0?"":"(dup)"); -  } - -  /* if we have an existing connection we need to kill that one -   * with this one */ -  if (mp->fd >= 0) { -    if (PIM_DEBUG_MSDP_EVENTS) { -      zlog_err("msdp duplicate connect to %s nuke old connection", mp->key_str); -    } -    pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); -  } - -  /* Make socket for the peer. */ -  mp->fd = sockunion_socket(&mp->su_peer); -  if (mp->fd < 0) { -    zlog_err ("pim_msdp_socket socket failure: %s", safe_strerror (errno)); -    return -1; -  } - -  set_nonblocking(mp->fd); - -  /* Set socket send buffer size */ -  pim_msdp_update_sock_send_buffer_size(mp->fd); -  sockopt_reuseaddr(mp->fd); -  sockopt_reuseport(mp->fd); - -  /* source bind */ -  rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local); -  if (rc < 0) { -    zlog_err ("pim_msdp_socket connect bind failure: %s", safe_strerror (errno)); -    close(mp->fd); -    mp->fd = -1; -    return rc; -  } - -  /* Connect to the remote mp. */ -  return (sockunion_connect(mp->fd, &mp->su_peer, htons(PIM_MSDP_TCP_PORT), 0)); +	int rc; + +	if (PIM_DEBUG_MSDP_INTERNAL) { +		zlog_debug("MSDP peer %s attempt connect%s", mp->key_str, +			   mp->fd < 0 ? "" : "(dup)"); +	} + +	/* if we have an existing connection we need to kill that one +	 * with this one */ +	if (mp->fd >= 0) { +		if (PIM_DEBUG_MSDP_EVENTS) { +			zlog_err( +				"msdp duplicate connect to %s nuke old connection", +				mp->key_str); +		} +		pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); +	} + +	/* Make socket for the peer. */ +	mp->fd = sockunion_socket(&mp->su_peer); +	if (mp->fd < 0) { +		zlog_err("pim_msdp_socket socket failure: %s", +			 safe_strerror(errno)); +		return -1; +	} + +	set_nonblocking(mp->fd); + +	/* Set socket send buffer size */ +	pim_msdp_update_sock_send_buffer_size(mp->fd); +	sockopt_reuseaddr(mp->fd); +	sockopt_reuseport(mp->fd); + +	/* source bind */ +	rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local); +	if (rc < 0) { +		zlog_err("pim_msdp_socket connect bind failure: %s", +			 safe_strerror(errno)); +		close(mp->fd); +		mp->fd = -1; +		return rc; +	} + +	/* Connect to the remote mp. */ +	return (sockunion_connect(mp->fd, &mp->su_peer, +				  htons(PIM_MSDP_TCP_PORT), 0));  } - diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index e077a85168..04f1f4846f 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -37,197 +37,202 @@  #include "pim_register.h"  #include "pim_jp_agg.h" -void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type) +void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, +			  uint8_t pim_msg_type)  { -  struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; - -  /* -   * Write header -   */ -  header->ver = PIM_PROTO_VERSION; -  header->type = pim_msg_type; -  header->reserved = 0; - - -  header->checksum = 0; -  /* -   * The checksum for Registers is done only on the first 8 bytes of the packet, -   * including the PIM header and the next 4 bytes, excluding the data packet portion -   */ -  if (pim_msg_type == PIM_MSG_TYPE_REGISTER) -    header->checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN); -  else -    header->checksum = in_cksum (pim_msg, pim_msg_size); +	struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; + +	/* +	 * Write header +	 */ +	header->ver = PIM_PROTO_VERSION; +	header->type = pim_msg_type; +	header->reserved = 0; + + +	header->checksum = 0; +	/* +	 * The checksum for Registers is done only on the first 8 bytes of the +	 * packet, +	 * including the PIM header and the next 4 bytes, excluding the data +	 * packet portion +	 */ +	if (pim_msg_type == PIM_MSG_TYPE_REGISTER) +		header->checksum = in_cksum(pim_msg, PIM_MSG_REGISTER_LEN); +	else +		header->checksum = in_cksum(pim_msg, pim_msg_size);  }  uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr)  { -  buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ -  buf[1] = '\0';    /* native encoding */ -  memcpy(buf+2, &addr, sizeof(struct in_addr)); +	buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ +	buf[1] = '\0';			      /* native encoding */ +	memcpy(buf + 2, &addr, sizeof(struct in_addr)); -  return buf + PIM_ENCODED_IPV4_UCAST_SIZE; +	return buf + PIM_ENCODED_IPV4_UCAST_SIZE;  }  uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr)  { -  buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ -  buf[1] = '\0';    /* native encoding */ -  buf[2] = '\0';    /* reserved */ -  buf[3] = 32;      /* mask len */ -  memcpy(buf+4, &addr, sizeof(struct in_addr)); +	buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ +	buf[1] = '\0';			      /* native encoding */ +	buf[2] = '\0';			      /* reserved */ +	buf[3] = 32;			      /* mask len */ +	memcpy(buf + 4, &addr, sizeof(struct in_addr)); -  return buf + PIM_ENCODED_IPV4_GROUP_SIZE; +	return buf + PIM_ENCODED_IPV4_GROUP_SIZE;  } -uint8_t * -pim_msg_addr_encode_ipv4_source(uint8_t *buf, -                                struct in_addr addr, uint8_t bits) +uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, +					 uint8_t bits)  { -  buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ -  buf[1] = '\0';    /* native encoding */ -  buf[2] = bits; -  buf[3] = 32;      /* mask len */ -  memcpy(buf+4, &addr, sizeof(struct in_addr)); +	buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ +	buf[1] = '\0';			      /* native encoding */ +	buf[2] = bits; +	buf[3] = 32; /* mask len */ +	memcpy(buf + 4, &addr, sizeof(struct in_addr)); -  return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; +	return buf + PIM_ENCODED_IPV4_SOURCE_SIZE;  }  /*   * For the given 'struct pim_jp_sources' list   * determine the size_t it would take up.   */ -size_t -pim_msg_get_jp_group_size (struct list *sources) +size_t pim_msg_get_jp_group_size(struct list *sources)  { -  struct pim_jp_sources *js; -  size_t size = 0; - -  size += sizeof (struct pim_encoded_group_ipv4); -  size += 4;  // Joined sources (2) + Pruned Sources (2) - -  size += sizeof (struct pim_encoded_source_ipv4) * sources->count; - -  js = listgetdata(listhead(sources)); -  if (js && js->up->sg.src.s_addr == INADDR_ANY) -    { -      struct pim_upstream *child, *up; -      struct listnode *up_node; - -      up = js->up; -      if (PIM_DEBUG_PIM_PACKETS) -        zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", -                    __PRETTY_FUNCTION__, up->sg_str); - -      for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) -        { -          if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) -            { -              if (!pim_rpf_is_same(&up->rpf, &child->rpf)) -                { -                  size += sizeof (struct pim_encoded_source_ipv4); -                  PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); -                  if (PIM_DEBUG_PIM_PACKETS) -                    zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", -                                __PRETTY_FUNCTION__, up->sg_str, child->sg_str); -                } -              else -                if (PIM_DEBUG_PIM_PACKETS) -                  zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", -                              __PRETTY_FUNCTION__, up->sg_str, child->sg_str); -            } -          else if (pim_upstream_is_sg_rpt (child)) -            { -              if (pim_upstream_empty_inherited_olist (child)) -                { -                  size += sizeof (struct pim_encoded_source_ipv4); -                  PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); -                  if (PIM_DEBUG_PIM_PACKETS) -                    zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", -                                __PRETTY_FUNCTION__, child->sg_str); -                } -              else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) -                { -                  size += sizeof (struct pim_encoded_source_ipv4); -                  PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); -                  if (PIM_DEBUG_PIM_PACKETS) -                    zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", -                                __PRETTY_FUNCTION__, up->sg_str, child->sg_str); -                } -              else -                if (PIM_DEBUG_PIM_PACKETS) -                  zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", -                              __PRETTY_FUNCTION__, up->sg_str, child->sg_str); -            } -          else -            if (PIM_DEBUG_PIM_PACKETS) -              zlog_debug ("%s: SPT bit is not set for (%s)", -                          __PRETTY_FUNCTION__, child->sg_str); -        } -    } -  return size; +	struct pim_jp_sources *js; +	size_t size = 0; + +	size += sizeof(struct pim_encoded_group_ipv4); +	size += 4; // Joined sources (2) + Pruned Sources (2) + +	size += sizeof(struct pim_encoded_source_ipv4) * sources->count; + +	js = listgetdata(listhead(sources)); +	if (js && js->up->sg.src.s_addr == INADDR_ANY) { +		struct pim_upstream *child, *up; +		struct listnode *up_node; + +		up = js->up; +		if (PIM_DEBUG_PIM_PACKETS) +			zlog_debug( +				"%s: Considering (%s) children for (S,G,rpt) prune", +				__PRETTY_FUNCTION__, up->sg_str); + +		for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { +			if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) { +				if (!pim_rpf_is_same(&up->rpf, &child->rpf)) { +					size += sizeof( +						struct pim_encoded_source_ipv4); +					PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( +						child->flags); +					if (PIM_DEBUG_PIM_PACKETS) +						zlog_debug( +							"%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", +							__PRETTY_FUNCTION__, +							up->sg_str, +							child->sg_str); +				} else if (PIM_DEBUG_PIM_PACKETS) +					zlog_debug( +						"%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", +						__PRETTY_FUNCTION__, up->sg_str, +						child->sg_str); +			} else if (pim_upstream_is_sg_rpt(child)) { +				if (pim_upstream_empty_inherited_olist(child)) { +					size += sizeof( +						struct pim_encoded_source_ipv4); +					PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( +						child->flags); +					if (PIM_DEBUG_PIM_PACKETS) +						zlog_debug( +							"%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", +							__PRETTY_FUNCTION__, +							child->sg_str); +				} else if (!pim_rpf_is_same(&up->rpf, +							    &child->rpf)) { +					size += sizeof( +						struct pim_encoded_source_ipv4); +					PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( +						child->flags); +					if (PIM_DEBUG_PIM_PACKETS) +						zlog_debug( +							"%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", +							__PRETTY_FUNCTION__, +							up->sg_str, +							child->sg_str); +				} else if (PIM_DEBUG_PIM_PACKETS) +					zlog_debug( +						"%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", +						__PRETTY_FUNCTION__, up->sg_str, +						child->sg_str); +			} else if (PIM_DEBUG_PIM_PACKETS) +				zlog_debug("%s: SPT bit is not set for (%s)", +					   __PRETTY_FUNCTION__, child->sg_str); +		} +	} +	return size;  } -size_t -pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size) +size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, +			       struct pim_jp_agg_group *sgs, size_t size)  { -  struct listnode *node, *nnode; -  struct pim_jp_sources *source; -  struct pim_upstream *up = NULL; -  struct in_addr stosend; -  uint8_t bits; -  uint8_t tgroups = 0; - -  memset (grp, 0, size); -  pim_msg_addr_encode_ipv4_group ((uint8_t *)&grp->g, sgs->group); - -  for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) -    { -      /* number of joined/pruned sources */ -      if (source->is_join) -        grp->joins++; -      else -        grp->prunes++; - -      if (source->up->sg.src.s_addr == INADDR_ANY) -        { -          struct pim_rpf *rpf = pim_rp_g (source->up->sg.grp); -          bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; -          stosend = rpf->rpf_addr.u.prefix4; -          /* Only Send SGRpt in case of *,G Join */ -          if (source->is_join) -            up = source->up; -        } -      else -        { -          bits = PIM_ENCODE_SPARSE_BIT; -          stosend = source->up->sg.src; -        } - -      pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], stosend, bits); -      tgroups++; -    } - -  if (up) -    { -      struct pim_upstream *child; - -      for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) -        { -          if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(child->flags)) -            { -              pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], -                                               child->sg.src, -                                               PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT); -              tgroups++; -              PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(child->flags); -              grp->prunes++; -            } -        } -    } - -  grp->joins = htons(grp->joins); -  grp->prunes = htons(grp->prunes); - -  return size; +	struct listnode *node, *nnode; +	struct pim_jp_sources *source; +	struct pim_upstream *up = NULL; +	struct in_addr stosend; +	uint8_t bits; +	uint8_t tgroups = 0; + +	memset(grp, 0, size); +	pim_msg_addr_encode_ipv4_group((uint8_t *)&grp->g, sgs->group); + +	for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) { +		/* number of joined/pruned sources */ +		if (source->is_join) +			grp->joins++; +		else +			grp->prunes++; + +		if (source->up->sg.src.s_addr == INADDR_ANY) { +			struct pim_rpf *rpf = pim_rp_g(source->up->sg.grp); +			bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT +			       | PIM_ENCODE_RPT_BIT; +			stosend = rpf->rpf_addr.u.prefix4; +			/* Only Send SGRpt in case of *,G Join */ +			if (source->is_join) +				up = source->up; +		} else { +			bits = PIM_ENCODE_SPARSE_BIT; +			stosend = source->up->sg.src; +		} + +		pim_msg_addr_encode_ipv4_source((uint8_t *)&grp->s[tgroups], +						stosend, bits); +		tgroups++; +	} + +	if (up) { +		struct pim_upstream *child; + +		for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) { +			if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE( +				    child->flags)) { +				pim_msg_addr_encode_ipv4_source( +					(uint8_t *)&grp->s[tgroups], +					child->sg.src, +					PIM_ENCODE_SPARSE_BIT +						| PIM_ENCODE_RPT_BIT); +				tgroups++; +				PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE( +					child->flags); +				grp->prunes++; +			} +		} +	} + +	grp->joins = htons(grp->joins); +	grp->prunes = htons(grp->prunes); + +	return size;  } diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 38ffaf6a7d..ad9b5d9c01 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -24,7 +24,7 @@  #include "pim_jp_agg.h"  /* -  Number       Description        +  Number       Description    ----------   ------------------    0            Reserved    1            IP (IP version 4) @@ -34,70 +34,72 @@    http://www.iana.org/assignments/address-family-numbers  */  enum pim_msg_address_family { -  PIM_MSG_ADDRESS_FAMILY_RESERVED, -  PIM_MSG_ADDRESS_FAMILY_IPV4, -  PIM_MSG_ADDRESS_FAMILY_IPV6, +	PIM_MSG_ADDRESS_FAMILY_RESERVED, +	PIM_MSG_ADDRESS_FAMILY_IPV4, +	PIM_MSG_ADDRESS_FAMILY_IPV6,  };  /*   * Network Order pim_msg_hdr   */  struct pim_msg_header { -  uint8_t  type:4; -  uint8_t  ver:4; -  uint8_t  reserved; -  uint16_t checksum; -} __attribute__ ((packed)); +	uint8_t type : 4; +	uint8_t ver : 4; +	uint8_t reserved; +	uint16_t checksum; +} __attribute__((packed));  struct pim_encoded_ipv4_unicast { -  uint8_t  family; -  uint8_t  reserved; -  struct in_addr addr; -} __attribute__ ((packed)); +	uint8_t family; +	uint8_t reserved; +	struct in_addr addr; +} __attribute__((packed));  struct pim_encoded_group_ipv4 { -  uint8_t        ne; -  uint8_t        family; -  uint8_t        reserved; -  uint8_t        mask; -  struct in_addr addr; -} __attribute__ ((packed)); +	uint8_t ne; +	uint8_t family; +	uint8_t reserved; +	uint8_t mask; +	struct in_addr addr; +} __attribute__((packed));  struct pim_encoded_source_ipv4 { -  uint8_t        ne; -  uint8_t        family; -  uint8_t        bits; -  uint8_t        mask; -  struct in_addr addr; -} __attribute__ ((packed)); +	uint8_t ne; +	uint8_t family; +	uint8_t bits; +	uint8_t mask; +	struct in_addr addr; +} __attribute__((packed));  struct pim_jp_groups { -  struct pim_encoded_group_ipv4  g; -  uint16_t                       joins; -  uint16_t                       prunes; -  struct pim_encoded_source_ipv4 s[1]; -} __attribute__ ((packed)); +	struct pim_encoded_group_ipv4 g; +	uint16_t joins; +	uint16_t prunes; +	struct pim_encoded_source_ipv4 s[1]; +} __attribute__((packed));  struct pim_jp { -  struct pim_msg_header           header; -  struct pim_encoded_ipv4_unicast addr; -  uint8_t                         reserved; -  uint8_t                         num_groups; -  uint16_t                        holdtime; -  struct pim_jp_groups            groups[1]; -} __attribute__ ((packed)); +	struct pim_msg_header header; +	struct pim_encoded_ipv4_unicast addr; +	uint8_t reserved; +	uint8_t num_groups; +	uint16_t holdtime; +	struct pim_jp_groups groups[1]; +} __attribute__((packed)); -void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type); +void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, +			  uint8_t pim_msg_type);  uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr);  uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr);  #define PIM_ENCODE_SPARSE_BIT      0x04  #define PIM_ENCODE_WC_BIT          0x02  #define PIM_ENCODE_RPT_BIT         0x01 -uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, -                                         struct in_addr addr, uint8_t bits); +uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, +					 uint8_t bits); -size_t pim_msg_get_jp_group_size (struct list *sources); -size_t pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size); +size_t pim_msg_get_jp_group_size(struct list *sources); +size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, +			       struct pim_jp_agg_group *sgs, size_t size);  #endif /* PIM_MSG_H */ diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 8b8946daf0..70341a3754 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -42,66 +42,61 @@  static void dr_election_by_addr(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct pim_neighbor  *neigh; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  pim_ifp->pim_dr_addr = pim_ifp->primary_address; - -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("%s: on interface %s", -	       __PRETTY_FUNCTION__, -	       ifp->name); -  } - -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { -    if (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) { -      pim_ifp->pim_dr_addr = neigh->source_addr; -    } -  } +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct pim_neighbor *neigh; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	pim_ifp->pim_dr_addr = pim_ifp->primary_address; + +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("%s: on interface %s", __PRETTY_FUNCTION__, +			   ifp->name); +	} + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { +		if (ntohl(neigh->source_addr.s_addr) +		    > ntohl(pim_ifp->pim_dr_addr.s_addr)) { +			pim_ifp->pim_dr_addr = neigh->source_addr; +		} +	}  }  static void dr_election_by_pri(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct pim_neighbor  *neigh; -  uint32_t              dr_pri; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  pim_ifp->pim_dr_addr = pim_ifp->primary_address; -  dr_pri = pim_ifp->pim_dr_priority; - -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("%s: dr pri %u on interface %s", -	       __PRETTY_FUNCTION__, -	       dr_pri, ifp->name); -  } - -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { -    if (PIM_DEBUG_PIM_TRACE) { -      zlog_info("%s: neigh pri %u addr %x if dr addr %x", -		__PRETTY_FUNCTION__, -		neigh->dr_priority, -		ntohl(neigh->source_addr.s_addr), -		ntohl(pim_ifp->pim_dr_addr.s_addr)); -    } -    if ( -	(neigh->dr_priority > dr_pri) || -	( -	 (neigh->dr_priority == dr_pri) && -	 (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) -	 ) -	) { -      pim_ifp->pim_dr_addr = neigh->source_addr; -      dr_pri               = neigh->dr_priority; -    } -  } +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct pim_neighbor *neigh; +	uint32_t dr_pri; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	pim_ifp->pim_dr_addr = pim_ifp->primary_address; +	dr_pri = pim_ifp->pim_dr_priority; + +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("%s: dr pri %u on interface %s", __PRETTY_FUNCTION__, +			   dr_pri, ifp->name); +	} + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { +		if (PIM_DEBUG_PIM_TRACE) { +			zlog_info("%s: neigh pri %u addr %x if dr addr %x", +				  __PRETTY_FUNCTION__, neigh->dr_priority, +				  ntohl(neigh->source_addr.s_addr), +				  ntohl(pim_ifp->pim_dr_addr.s_addr)); +		} +		if ((neigh->dr_priority > dr_pri) +		    || ((neigh->dr_priority == dr_pri) +			&& (ntohl(neigh->source_addr.s_addr) +			    > ntohl(pim_ifp->pim_dr_addr.s_addr)))) { +			pim_ifp->pim_dr_addr = neigh->source_addr; +			dr_pri = neigh->dr_priority; +		} +	}  }  /* @@ -113,359 +108,359 @@ static void dr_election_by_pri(struct interface *ifp)   */  int pim_if_dr_election(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct in_addr old_dr_addr; - -  ++pim_ifp->pim_dr_election_count; - -  old_dr_addr = pim_ifp->pim_dr_addr; - -  if (pim_ifp->pim_dr_num_nondrpri_neighbors) { -    dr_election_by_addr(ifp); -  } -  else { -    dr_election_by_pri(ifp); -  } - -  /* DR changed ? */ -  if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) { - -    if (PIM_DEBUG_PIM_EVENTS) { -      char dr_old_str[INET_ADDRSTRLEN]; -      char dr_new_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str)); -      pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str)); -      zlog_debug("%s: DR was %s now is %s on interface %s", -		 __PRETTY_FUNCTION__, -		 dr_old_str, dr_new_str, ifp->name); -    } - -    pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */ -    ++pim_ifp->pim_dr_election_changes;  -    pim_if_update_join_desired(pim_ifp); -    pim_if_update_could_assert(ifp); -    pim_if_update_assert_tracking_desired(ifp); -    return 1; -  } - -  return 0; +	struct pim_interface *pim_ifp = ifp->info; +	struct in_addr old_dr_addr; + +	++pim_ifp->pim_dr_election_count; + +	old_dr_addr = pim_ifp->pim_dr_addr; + +	if (pim_ifp->pim_dr_num_nondrpri_neighbors) { +		dr_election_by_addr(ifp); +	} else { +		dr_election_by_pri(ifp); +	} + +	/* DR changed ? */ +	if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) { + +		if (PIM_DEBUG_PIM_EVENTS) { +			char dr_old_str[INET_ADDRSTRLEN]; +			char dr_new_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, +				       sizeof(dr_old_str)); +			pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, +				       dr_new_str, sizeof(dr_new_str)); +			zlog_debug("%s: DR was %s now is %s on interface %s", +				   __PRETTY_FUNCTION__, dr_old_str, dr_new_str, +				   ifp->name); +		} + +		pim_ifp->pim_dr_election_last = +			pim_time_monotonic_sec(); /* timestamp */ +		++pim_ifp->pim_dr_election_changes; +		pim_if_update_join_desired(pim_ifp); +		pim_if_update_could_assert(ifp); +		pim_if_update_assert_tracking_desired(ifp); +		return 1; +	} + +	return 0;  }  static void update_dr_priority(struct pim_neighbor *neigh,  			       pim_hello_options hello_options,  			       uint32_t dr_priority)  { -  pim_hello_options will_set_pri; /* boolean */ -  pim_hello_options bit_flip;     /* boolean */ -  pim_hello_options pri_change;   /* boolean */ - -  will_set_pri = PIM_OPTION_IS_SET(hello_options, -				   PIM_OPTION_MASK_DR_PRIORITY); - -  bit_flip = -    ( -     will_set_pri != -     PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) -     ); - -  if (bit_flip) { -    struct pim_interface *pim_ifp = neigh->interface->info; - -    /* update num. of neighbors without dr_pri */ - -    if (will_set_pri) { -      --pim_ifp->pim_dr_num_nondrpri_neighbors;  -    } -    else { -      ++pim_ifp->pim_dr_num_nondrpri_neighbors;  -    } -  } - -  pri_change =  -    ( -     bit_flip -     || -     (neigh->dr_priority != dr_priority) -     ); - -  if (will_set_pri) { -    neigh->dr_priority = dr_priority; -  } -  else { -    neigh->dr_priority = 0; /* cosmetic unset */ -  } - -  if (pri_change) { -    /* -      RFC 4601: 4.3.2.  DR Election -       -      A router's idea of the current DR on an interface can change when a -      PIM Hello message is received, when a neighbor times out, or when a -      router's own DR Priority changes. -    */ -    pim_if_dr_election(neigh->interface); // router's own DR Priority changes -  } +	pim_hello_options will_set_pri; /* boolean */ +	pim_hello_options bit_flip;     /* boolean */ +	pim_hello_options pri_change;   /* boolean */ + +	will_set_pri = +		PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY); + +	bit_flip = (will_set_pri +		    != PIM_OPTION_IS_SET(neigh->hello_options, +					 PIM_OPTION_MASK_DR_PRIORITY)); + +	if (bit_flip) { +		struct pim_interface *pim_ifp = neigh->interface->info; + +		/* update num. of neighbors without dr_pri */ + +		if (will_set_pri) { +			--pim_ifp->pim_dr_num_nondrpri_neighbors; +		} else { +			++pim_ifp->pim_dr_num_nondrpri_neighbors; +		} +	} + +	pri_change = (bit_flip || (neigh->dr_priority != dr_priority)); + +	if (will_set_pri) { +		neigh->dr_priority = dr_priority; +	} else { +		neigh->dr_priority = 0; /* cosmetic unset */ +	} + +	if (pri_change) { +		/* +		  RFC 4601: 4.3.2.  DR Election + +		  A router's idea of the current DR on an interface can change +		  when a +		  PIM Hello message is received, when a neighbor times out, or +		  when a +		  router's own DR Priority changes. +		*/ +		pim_if_dr_election( +			neigh->interface); // router's own DR Priority changes +	}  }  static int on_neighbor_timer(struct thread *t)  { -  struct pim_neighbor *neigh; -  struct interface *ifp; -  char msg[100]; - -  neigh = THREAD_ARG(t); - -  ifp = neigh->interface; - -  if (PIM_DEBUG_PIM_TRACE) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); -    zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s", -	       neigh->holdtime, src_str, ifp->name); -  } - -  snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); -  pim_neighbor_delete(ifp, neigh, msg); - -  /* -    RFC 4601: 4.3.2.  DR Election -     -    A router's idea of the current DR on an interface can change when a -    PIM Hello message is received, when a neighbor times out, or when a -    router's own DR Priority changes. -  */ -  pim_if_dr_election(ifp); // neighbor times out - -  return 0; +	struct pim_neighbor *neigh; +	struct interface *ifp; +	char msg[100]; + +	neigh = THREAD_ARG(t); + +	ifp = neigh->interface; + +	if (PIM_DEBUG_PIM_TRACE) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", neigh->source_addr, src_str, +			       sizeof(src_str)); +		zlog_debug( +			"Expired %d sec holdtime for neighbor %s on interface %s", +			neigh->holdtime, src_str, ifp->name); +	} + +	snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); +	pim_neighbor_delete(ifp, neigh, msg); + +	/* +	  RFC 4601: 4.3.2.  DR Election + +	  A router's idea of the current DR on an interface can change when a +	  PIM Hello message is received, when a neighbor times out, or when a +	  router's own DR Priority changes. +	*/ +	pim_if_dr_election(ifp); // neighbor times out + +	return 0;  }  void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)  { -  neigh->holdtime = holdtime; - -  THREAD_OFF(neigh->t_expire_timer); - -  /* -    0xFFFF is request for no holdtime -   */ -  if (neigh->holdtime == 0xFFFF) { -    return; -  } - -  if (PIM_DEBUG_PIM_TRACE_DETAIL) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); -    zlog_debug("%s: starting %u sec timer for neighbor %s on %s", -	       __PRETTY_FUNCTION__, -	       neigh->holdtime, src_str, neigh->interface->name); -  } - -  thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime, -                   &neigh->t_expire_timer); +	neigh->holdtime = holdtime; + +	THREAD_OFF(neigh->t_expire_timer); + +	/* +	  0xFFFF is request for no holdtime +	 */ +	if (neigh->holdtime == 0xFFFF) { +		return; +	} + +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", neigh->source_addr, src_str, +			       sizeof(src_str)); +		zlog_debug("%s: starting %u sec timer for neighbor %s on %s", +			   __PRETTY_FUNCTION__, neigh->holdtime, src_str, +			   neigh->interface->name); +	} + +	thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime, +			 &neigh->t_expire_timer);  } -static int -on_neighbor_jp_timer (struct thread *t) +static int on_neighbor_jp_timer(struct thread *t)  { -  struct pim_neighbor *neigh = THREAD_ARG(t); -  struct pim_rpf rpf; - -  if (PIM_DEBUG_PIM_TRACE) -    { -      char src_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); -      zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", __PRETTY_FUNCTION__, -                 src_str, neigh->interface->name, neigh->upstream_jp_agg->count); -    } +	struct pim_neighbor *neigh = THREAD_ARG(t); +	struct pim_rpf rpf; + +	if (PIM_DEBUG_PIM_TRACE) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", neigh->source_addr, src_str, +			       sizeof(src_str)); +		zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", +			   __PRETTY_FUNCTION__, src_str, neigh->interface->name, +			   neigh->upstream_jp_agg->count); +	} -  rpf.source_nexthop.interface = neigh->interface; -  rpf.rpf_addr.u.prefix4 = neigh->source_addr; -  pim_joinprune_send(&rpf, neigh->upstream_jp_agg); +	rpf.source_nexthop.interface = neigh->interface; +	rpf.rpf_addr.u.prefix4 = neigh->source_addr; +	pim_joinprune_send(&rpf, neigh->upstream_jp_agg); -  thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, -                   &neigh->jp_timer); +	thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, +			 &neigh->jp_timer); -  return 0; +	return 0;  } -static void -pim_neighbor_start_jp_timer (struct pim_neighbor *neigh) +static void pim_neighbor_start_jp_timer(struct pim_neighbor *neigh)  { -  THREAD_TIMER_OFF(neigh->jp_timer); -  thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, -                   &neigh->jp_timer); +	THREAD_TIMER_OFF(neigh->jp_timer); +	thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, +			 &neigh->jp_timer);  } -static struct pim_neighbor *pim_neighbor_new(struct interface *ifp, -					     struct in_addr source_addr, -					     pim_hello_options hello_options, -					     uint16_t holdtime, -					     uint16_t propagation_delay, -					     uint16_t override_interval, -					     uint32_t dr_priority, -					     uint32_t generation_id, -					     struct list *addr_list) +static struct pim_neighbor * +pim_neighbor_new(struct interface *ifp, struct in_addr source_addr, +		 pim_hello_options hello_options, uint16_t holdtime, +		 uint16_t propagation_delay, uint16_t override_interval, +		 uint32_t dr_priority, uint32_t generation_id, +		 struct list *addr_list)  { -  struct pim_interface *pim_ifp; -  struct pim_neighbor *neigh; -  char src_str[INET_ADDRSTRLEN]; - -  zassert(ifp); -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); -  if (!neigh) { -    zlog_err("%s: PIM XCALLOC(%zu) failure", -	     __PRETTY_FUNCTION__, sizeof(*neigh)); -    return 0; -  } - -  neigh->creation               = pim_time_monotonic_sec(); -  neigh->source_addr            = source_addr; -  neigh->hello_options          = hello_options; -  neigh->propagation_delay_msec = propagation_delay; -  neigh->override_interval_msec = override_interval; -  neigh->dr_priority            = dr_priority; -  neigh->generation_id          = generation_id; -  neigh->prefix_list            = addr_list; -  neigh->t_expire_timer         = NULL; -  neigh->interface              = ifp; - -  neigh->upstream_jp_agg = list_new(); -  neigh->upstream_jp_agg->cmp = pim_jp_agg_group_list_cmp; -  neigh->upstream_jp_agg->del = (void (*)(void *))pim_jp_agg_group_list_free; -  pim_neighbor_start_jp_timer(neigh); - -  pim_neighbor_timer_reset(neigh, holdtime); -  /* -   * The pim_ifstat_hello_sent variable is used to decide if -   * we should expedite a hello out the interface.  If we -   * establish a new neighbor, we unfortunately need to -   * reset the value so that we can know to hurry up and -   * hello -   */ -  pim_ifp->pim_ifstat_hello_sent = 0; - -  pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str)); - -  if (PIM_DEBUG_PIM_EVENTS) { -    zlog_debug("%s: creating PIM neighbor %s on interface %s", -	       __PRETTY_FUNCTION__, -	       src_str, ifp->name); -  } - -  zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", -	    src_str, ifp->name); - -  if (neigh->propagation_delay_msec > pim_ifp->pim_neighbors_highest_propagation_delay_msec) { -    pim_ifp->pim_neighbors_highest_propagation_delay_msec = neigh->propagation_delay_msec; -  } -  if (neigh->override_interval_msec > pim_ifp->pim_neighbors_highest_override_interval_msec) { -    pim_ifp->pim_neighbors_highest_override_interval_msec = neigh->override_interval_msec; -  } - -  if (!PIM_OPTION_IS_SET(neigh->hello_options, -			 PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { -    /* update num. of neighbors without hello option lan_delay */ -    ++pim_ifp->pim_number_of_nonlandelay_neighbors;  -  } - -  if (!PIM_OPTION_IS_SET(neigh->hello_options, -			 PIM_OPTION_MASK_DR_PRIORITY)) { -    /* update num. of neighbors without hello option dr_pri */ -    ++pim_ifp->pim_dr_num_nondrpri_neighbors;  -  } - -  //Register PIM Neighbor with BFD -  pim_bfd_trigger_event (pim_ifp, neigh, 1); - -  return neigh; +	struct pim_interface *pim_ifp; +	struct pim_neighbor *neigh; +	char src_str[INET_ADDRSTRLEN]; + +	zassert(ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); +	if (!neigh) { +		zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, +			 sizeof(*neigh)); +		return 0; +	} + +	neigh->creation = pim_time_monotonic_sec(); +	neigh->source_addr = source_addr; +	neigh->hello_options = hello_options; +	neigh->propagation_delay_msec = propagation_delay; +	neigh->override_interval_msec = override_interval; +	neigh->dr_priority = dr_priority; +	neigh->generation_id = generation_id; +	neigh->prefix_list = addr_list; +	neigh->t_expire_timer = NULL; +	neigh->interface = ifp; + +	neigh->upstream_jp_agg = list_new(); +	neigh->upstream_jp_agg->cmp = pim_jp_agg_group_list_cmp; +	neigh->upstream_jp_agg->del = +		(void (*)(void *))pim_jp_agg_group_list_free; +	pim_neighbor_start_jp_timer(neigh); + +	pim_neighbor_timer_reset(neigh, holdtime); +	/* +	 * The pim_ifstat_hello_sent variable is used to decide if +	 * we should expedite a hello out the interface.  If we +	 * establish a new neighbor, we unfortunately need to +	 * reset the value so that we can know to hurry up and +	 * hello +	 */ +	pim_ifp->pim_ifstat_hello_sent = 0; + +	pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str)); + +	if (PIM_DEBUG_PIM_EVENTS) { +		zlog_debug("%s: creating PIM neighbor %s on interface %s", +			   __PRETTY_FUNCTION__, src_str, ifp->name); +	} + +	zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", src_str, +		  ifp->name); + +	if (neigh->propagation_delay_msec +	    > pim_ifp->pim_neighbors_highest_propagation_delay_msec) { +		pim_ifp->pim_neighbors_highest_propagation_delay_msec = +			neigh->propagation_delay_msec; +	} +	if (neigh->override_interval_msec +	    > pim_ifp->pim_neighbors_highest_override_interval_msec) { +		pim_ifp->pim_neighbors_highest_override_interval_msec = +			neigh->override_interval_msec; +	} + +	if (!PIM_OPTION_IS_SET(neigh->hello_options, +			       PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { +		/* update num. of neighbors without hello option lan_delay */ +		++pim_ifp->pim_number_of_nonlandelay_neighbors; +	} + +	if (!PIM_OPTION_IS_SET(neigh->hello_options, +			       PIM_OPTION_MASK_DR_PRIORITY)) { +		/* update num. of neighbors without hello option dr_pri */ +		++pim_ifp->pim_dr_num_nondrpri_neighbors; +	} + +	// Register PIM Neighbor with BFD +	pim_bfd_trigger_event(pim_ifp, neigh, 1); + +	return neigh;  }  static void delete_prefix_list(struct pim_neighbor *neigh)  { -  if (neigh->prefix_list) { +	if (neigh->prefix_list) {  #ifdef DUMP_PREFIX_LIST -    struct listnode *p_node; -    struct prefix *p; -    char addr_str[10]; -    int list_size = neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1; -    int i = 0; -    for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) { -      pim_inet4_dump("<addr?>", p->u.prefix4, addr_str, sizeof(addr_str)); -      zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]", -		 __PRETTY_FUNCTION__, -		 (unsigned) neigh, (unsigned) neigh->prefix_list, (unsigned) p, -		 addr_str, i, list_size); -      ++i; -    } +		struct listnode *p_node; +		struct prefix *p; +		char addr_str[10]; +		int list_size = neigh->prefix_list +					? (int)listcount(neigh->prefix_list) +					: -1; +		int i = 0; +		for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) { +			pim_inet4_dump("<addr?>", p->u.prefix4, addr_str, +				       sizeof(addr_str)); +			zlog_debug( +				"%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]", +				__PRETTY_FUNCTION__, (unsigned)neigh, +				(unsigned)neigh->prefix_list, (unsigned)p, +				addr_str, i, list_size); +			++i; +		}  #endif -    list_delete(neigh->prefix_list); -    neigh->prefix_list = 0; -  } +		list_delete(neigh->prefix_list); +		neigh->prefix_list = 0; +	}  }  void pim_neighbor_free(struct pim_neighbor *neigh)  { -  zassert(!neigh->t_expire_timer); +	zassert(!neigh->t_expire_timer); -  delete_prefix_list(neigh); +	delete_prefix_list(neigh); -  list_delete(neigh->upstream_jp_agg); -  THREAD_OFF(neigh->jp_timer); +	list_delete(neigh->upstream_jp_agg); +	THREAD_OFF(neigh->jp_timer); -  XFREE(MTYPE_PIM_NEIGHBOR, neigh); +	XFREE(MTYPE_PIM_NEIGHBOR, neigh);  } -struct pim_neighbor * -pim_neighbor_find_by_secondary (struct interface *ifp, -                                struct prefix *src) +struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp, +						    struct prefix *src)  { -  struct pim_interface *pim_ifp; -  struct listnode *node, *pnode; -  struct pim_neighbor *neigh; -  struct prefix *p; - -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return NULL; - -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) -    { -      for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) -        { -          if (prefix_same (p, src)) -            return neigh; -        } -    } - -  return NULL; +	struct pim_interface *pim_ifp; +	struct listnode *node, *pnode; +	struct pim_neighbor *neigh; +	struct prefix *p; + +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return NULL; + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { +		for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) { +			if (prefix_same(p, src)) +				return neigh; +		} +	} + +	return NULL;  }  struct pim_neighbor *pim_neighbor_find(struct interface *ifp,  				       struct in_addr source_addr)  { -  struct pim_interface *pim_ifp; -  struct listnode      *node; -  struct pim_neighbor  *neigh; +	struct pim_interface *pim_ifp; +	struct listnode *node; +	struct pim_neighbor *neigh; -  if (!ifp) -    return NULL; +	if (!ifp) +		return NULL; -  pim_ifp = ifp->info; -  if (!pim_ifp) -    return NULL; +	pim_ifp = ifp->info; +	if (!pim_ifp) +		return NULL; -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { -    if (source_addr.s_addr == neigh->source_addr.s_addr) { -      return neigh; -    } -  } +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { +		if (source_addr.s_addr == neigh->source_addr.s_addr) { +			return neigh; +		} +	} -  return NULL; +	return NULL;  }  /* @@ -473,263 +468,256 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp,   * this interface.  If more than   * one return NULL   */ -struct pim_neighbor * -pim_neighbor_find_if (struct interface *ifp) +struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; +	struct pim_interface *pim_ifp = ifp->info; -  if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1) -    return NULL; +	if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1) +		return NULL; -  return listnode_head (pim_ifp->pim_neighbor_list); +	return listnode_head(pim_ifp->pim_neighbor_list);  }  /* rpf info associated with an upstream entry needs to be re-evaluated   * when an RPF neighbor comes or goes */ -static void -pim_neighbor_rpf_update(void) -{ -  /* XXX: for the time being piggyback on the timer used on rib changes -   * to scan and update the rpf nexthop. This is expensive processing -   * and we should be able to optimize neighbor changes differently than -   * nexthop changes. */ -  sched_rpf_cache_refresh(); -} - -struct pim_neighbor *pim_neighbor_add(struct interface *ifp, -				      struct in_addr source_addr, -				      pim_hello_options hello_options, -				      uint16_t holdtime, -				      uint16_t propagation_delay, -				      uint16_t override_interval, -				      uint32_t dr_priority, -				      uint32_t generation_id, -				      struct list *addr_list, -				      int send_hello_now) +static void pim_neighbor_rpf_update(void)  { -  struct pim_interface *pim_ifp; -  struct pim_neighbor *neigh; - -  neigh = pim_neighbor_new(ifp, source_addr, -			   hello_options, -			   holdtime, -			   propagation_delay, -			   override_interval, -			   dr_priority, -			   generation_id, -			   addr_list); -  if (!neigh) { -    return 0; -  } - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  listnode_add(pim_ifp->pim_neighbor_list, neigh); - -  if (PIM_DEBUG_PIM_TRACE_DETAIL) -    { -      char str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<nht_nbr?>", source_addr, str, sizeof (str)); -      zlog_debug ("%s: neighbor %s added ", __PRETTY_FUNCTION__, str); -    } -  /* -    RFC 4601: 4.3.2.  DR Election - -    A router's idea of the current DR on an interface can change when a -    PIM Hello message is received, when a neighbor times out, or when a -    router's own DR Priority changes. -  */ -  pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election... - -  /* -    RFC 4601: 4.3.1.  Sending Hello Messages - -    To allow new or rebooting routers to learn of PIM neighbors quickly, -    when a Hello message is received from a new neighbor, or a Hello -    message with a new GenID is received from an existing neighbor, a -    new Hello message should be sent on this interface after a -    randomized delay between 0 and Triggered_Hello_Delay. - -    This is a bit silly to do it that way.  If I get a new -    genid we need to send the hello *now* because we've -    lined up a bunch of join/prune messages to go out the -    interface. -  */ -  if (send_hello_now) -    pim_hello_restart_now (ifp); -  else -    pim_hello_restart_triggered(neigh->interface); - -  pim_upstream_find_new_rpf(); - -  /* RNH can send nexthop update prior to PIM neibhor UP -     in that case nexthop cache would not consider this neighbor -     as RPF. -     Upon PIM neighbor UP, iterate all RPs and update -     nexthop cache with this neighbor. -   */ -  pim_resolve_rp_nh (); - -  pim_rp_setup (); - -  pim_neighbor_rpf_update(); -  return neigh; +	/* XXX: for the time being piggyback on the timer used on rib changes +	 * to scan and update the rpf nexthop. This is expensive processing +	 * and we should be able to optimize neighbor changes differently than +	 * nexthop changes. */ +	sched_rpf_cache_refresh();  } -static uint16_t -find_neighbors_next_highest_propagation_delay_msec(struct interface *ifp, -						   struct pim_neighbor *highest_neigh) +struct pim_neighbor * +pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, +		 pim_hello_options hello_options, uint16_t holdtime, +		 uint16_t propagation_delay, uint16_t override_interval, +		 uint32_t dr_priority, uint32_t generation_id, +		 struct list *addr_list, int send_hello_now)  { -  struct pim_interface *pim_ifp; -  struct listnode *neigh_node; -  struct pim_neighbor *neigh; -  uint16_t next_highest_delay_msec; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	struct pim_interface *pim_ifp; +	struct pim_neighbor *neigh; + +	neigh = pim_neighbor_new(ifp, source_addr, hello_options, holdtime, +				 propagation_delay, override_interval, +				 dr_priority, generation_id, addr_list); +	if (!neigh) { +		return 0; +	} -  next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec; +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { -    if (neigh == highest_neigh) -      continue; -    if (neigh->propagation_delay_msec > next_highest_delay_msec) -      next_highest_delay_msec = neigh->propagation_delay_msec; -  } +	listnode_add(pim_ifp->pim_neighbor_list, neigh); -  return next_highest_delay_msec; +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		char str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<nht_nbr?>", source_addr, str, sizeof(str)); +		zlog_debug("%s: neighbor %s added ", __PRETTY_FUNCTION__, str); +	} +	/* +	  RFC 4601: 4.3.2.  DR Election + +	  A router's idea of the current DR on an interface can change when a +	  PIM Hello message is received, when a neighbor times out, or when a +	  router's own DR Priority changes. +	*/ +	pim_if_dr_election(neigh->interface); // new neighbor -- should not +					      // trigger dr election... + +	/* +	  RFC 4601: 4.3.1.  Sending Hello Messages + +	  To allow new or rebooting routers to learn of PIM neighbors quickly, +	  when a Hello message is received from a new neighbor, or a Hello +	  message with a new GenID is received from an existing neighbor, a +	  new Hello message should be sent on this interface after a +	  randomized delay between 0 and Triggered_Hello_Delay. + +	  This is a bit silly to do it that way.  If I get a new +	  genid we need to send the hello *now* because we've +	  lined up a bunch of join/prune messages to go out the +	  interface. +	*/ +	if (send_hello_now) +		pim_hello_restart_now(ifp); +	else +		pim_hello_restart_triggered(neigh->interface); + +	pim_upstream_find_new_rpf(); + +	/* RNH can send nexthop update prior to PIM neibhor UP +	   in that case nexthop cache would not consider this neighbor +	   as RPF. +	   Upon PIM neighbor UP, iterate all RPs and update +	   nexthop cache with this neighbor. +	 */ +	pim_resolve_rp_nh(); + +	pim_rp_setup(); + +	pim_neighbor_rpf_update(); +	return neigh;  } -static uint16_t -find_neighbors_next_highest_override_interval_msec(struct interface *ifp, -						   struct pim_neighbor *highest_neigh) +static uint16_t find_neighbors_next_highest_propagation_delay_msec( +	struct interface *ifp, struct pim_neighbor *highest_neigh)  { -  struct pim_interface *pim_ifp; -  struct listnode *neigh_node; -  struct pim_neighbor *neigh; -  uint16_t next_highest_interval_msec; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	struct pim_interface *pim_ifp; +	struct listnode *neigh_node; +	struct pim_neighbor *neigh; +	uint16_t next_highest_delay_msec; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec; + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, +				  neigh)) { +		if (neigh == highest_neigh) +			continue; +		if (neigh->propagation_delay_msec > next_highest_delay_msec) +			next_highest_delay_msec = neigh->propagation_delay_msec; +	} -  next_highest_interval_msec = pim_ifp->pim_override_interval_msec; +	return next_highest_delay_msec; +} -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { -    if (neigh == highest_neigh) -      continue; -    if (neigh->override_interval_msec > next_highest_interval_msec) -      next_highest_interval_msec = neigh->override_interval_msec; -  } +static uint16_t find_neighbors_next_highest_override_interval_msec( +	struct interface *ifp, struct pim_neighbor *highest_neigh) +{ +	struct pim_interface *pim_ifp; +	struct listnode *neigh_node; +	struct pim_neighbor *neigh; +	uint16_t next_highest_interval_msec; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	next_highest_interval_msec = pim_ifp->pim_override_interval_msec; + +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, +				  neigh)) { +		if (neigh == highest_neigh) +			continue; +		if (neigh->override_interval_msec > next_highest_interval_msec) +			next_highest_interval_msec = +				neigh->override_interval_msec; +	} -  return next_highest_interval_msec; +	return next_highest_interval_msec;  } -void pim_neighbor_delete(struct interface *ifp, -			 struct pim_neighbor *neigh, +void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,  			 const char *delete_message)  { -  struct pim_interface *pim_ifp; -  char src_str[INET_ADDRSTRLEN]; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); -  zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", -	    src_str, ifp->name, delete_message); +	struct pim_interface *pim_ifp; +	char src_str[INET_ADDRSTRLEN]; -  THREAD_OFF(neigh->t_expire_timer); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  pim_if_assert_on_neighbor_down(ifp, neigh->source_addr); +	pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); +	zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str, +		  ifp->name, delete_message); -  if (!PIM_OPTION_IS_SET(neigh->hello_options, -                         PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { -    /* update num. of neighbors without hello option lan_delay */ +	THREAD_OFF(neigh->t_expire_timer); -    --pim_ifp->pim_number_of_nonlandelay_neighbors; -  } +	pim_if_assert_on_neighbor_down(ifp, neigh->source_addr); -  if (!PIM_OPTION_IS_SET(neigh->hello_options, -			 PIM_OPTION_MASK_DR_PRIORITY)) { -    /* update num. of neighbors without dr_pri */ +	if (!PIM_OPTION_IS_SET(neigh->hello_options, +			       PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { +		/* update num. of neighbors without hello option lan_delay */ -    --pim_ifp->pim_dr_num_nondrpri_neighbors;  -  } - -  zassert(neigh->propagation_delay_msec <= pim_ifp->pim_neighbors_highest_propagation_delay_msec); -  zassert(neigh->override_interval_msec <= pim_ifp->pim_neighbors_highest_override_interval_msec); +		--pim_ifp->pim_number_of_nonlandelay_neighbors; +	} -  if (pim_if_lan_delay_enabled(ifp)) { +	if (!PIM_OPTION_IS_SET(neigh->hello_options, +			       PIM_OPTION_MASK_DR_PRIORITY)) { +		/* update num. of neighbors without dr_pri */ -    /* will delete a neighbor with highest propagation delay? */ -    if (neigh->propagation_delay_msec == pim_ifp->pim_neighbors_highest_propagation_delay_msec) { -      /* then find the next highest propagation delay */ -      pim_ifp->pim_neighbors_highest_propagation_delay_msec = -	find_neighbors_next_highest_propagation_delay_msec(ifp, neigh); -    } +		--pim_ifp->pim_dr_num_nondrpri_neighbors; +	} -    /* will delete a neighbor with highest override interval? */ -    if (neigh->override_interval_msec == pim_ifp->pim_neighbors_highest_override_interval_msec) { -      /* then find the next highest propagation delay */ -      pim_ifp->pim_neighbors_highest_override_interval_msec = -	find_neighbors_next_highest_override_interval_msec(ifp, neigh); -    } -  } +	zassert(neigh->propagation_delay_msec +		<= pim_ifp->pim_neighbors_highest_propagation_delay_msec); +	zassert(neigh->override_interval_msec +		<= pim_ifp->pim_neighbors_highest_override_interval_msec); + +	if (pim_if_lan_delay_enabled(ifp)) { + +		/* will delete a neighbor with highest propagation delay? */ +		if (neigh->propagation_delay_msec +		    == pim_ifp->pim_neighbors_highest_propagation_delay_msec) { +			/* then find the next highest propagation delay */ +			pim_ifp->pim_neighbors_highest_propagation_delay_msec = +				find_neighbors_next_highest_propagation_delay_msec( +					ifp, neigh); +		} + +		/* will delete a neighbor with highest override interval? */ +		if (neigh->override_interval_msec +		    == pim_ifp->pim_neighbors_highest_override_interval_msec) { +			/* then find the next highest propagation delay */ +			pim_ifp->pim_neighbors_highest_override_interval_msec = +				find_neighbors_next_highest_override_interval_msec( +					ifp, neigh); +		} +	} -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("%s: deleting PIM neighbor %s on interface %s", -	       __PRETTY_FUNCTION__, -	       src_str, ifp->name); -  } +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("%s: deleting PIM neighbor %s on interface %s", +			   __PRETTY_FUNCTION__, src_str, ifp->name); +	} -  //De-Register PIM Neighbor with BFD -  pim_bfd_trigger_event (pim_ifp, neigh, 0); +	// De-Register PIM Neighbor with BFD +	pim_bfd_trigger_event(pim_ifp, neigh, 0); -  listnode_delete(pim_ifp->pim_neighbor_list, neigh); +	listnode_delete(pim_ifp->pim_neighbor_list, neigh); -  pim_neighbor_free(neigh); +	pim_neighbor_free(neigh); -  pim_neighbor_rpf_update(); +	pim_neighbor_rpf_update();  } -void pim_neighbor_delete_all(struct interface *ifp, -			     const char *delete_message) +void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message)  { -  struct pim_interface *pim_ifp; -  struct listnode *neigh_node; -  struct listnode *neigh_nextnode; -  struct pim_neighbor *neigh; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, -			 neigh_nextnode, neigh)) { -    pim_neighbor_delete(ifp, neigh, delete_message); -  } +	struct pim_interface *pim_ifp; +	struct listnode *neigh_node; +	struct listnode *neigh_nextnode; +	struct pim_neighbor *neigh; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, +			       neigh_nextnode, neigh)) { +		pim_neighbor_delete(ifp, neigh, delete_message); +	}  }  struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,  					   struct prefix *addr)  { -  struct listnode *node; -  struct prefix   *p; +	struct listnode *node; +	struct prefix *p; -  if (!neigh->prefix_list) -    return 0; +	if (!neigh->prefix_list) +		return 0; -  for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { -    if (prefix_same (p, addr)) -      return p; -  } +	for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { +		if (prefix_same(p, addr)) +			return p; +	} -  return NULL; +	return NULL;  }  /*    RFC 4601: 4.3.4.  Maintaining Secondary Address Lists -   +    All the advertised secondary addresses in received Hello messages    must be checked against those previously advertised by all other    PIM neighbors on that interface.  If there is a conflict and the @@ -742,104 +730,109 @@ static void delete_from_neigh_addr(struct interface *ifp,  				   struct list *addr_list,  				   struct in_addr neigh_addr)  { -  struct listnode      *addr_node; -  struct prefix        *addr; -  struct pim_interface *pim_ifp; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  zassert(addr_list); - -  /* -    Scan secondary address list -  */ -  for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node, -			    addr)) { -    struct listnode      *neigh_node; -    struct pim_neighbor  *neigh; - -    if (addr->family != AF_INET) -      continue; - -    /* -      Scan neighbors -    */ -    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, -			      neigh)) { -      { -	struct prefix *p = pim_neighbor_find_secondary(neigh, addr); -	if (p) { -	  char addr_str[INET_ADDRSTRLEN]; -	  char this_neigh_str[INET_ADDRSTRLEN]; -	  char other_neigh_str[INET_ADDRSTRLEN]; -	   -	  pim_inet4_dump("<addr?>", addr->u.prefix4, addr_str, sizeof(addr_str)); -	  pim_inet4_dump("<neigh1?>", neigh_addr, this_neigh_str, sizeof(this_neigh_str)); -	  pim_inet4_dump("<neigh2?>", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str)); -	   -	  zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s", -		    addr_str, this_neigh_str, other_neigh_str, ifp->name); -	   -	  listnode_delete(neigh->prefix_list, p); -	  prefix_free(p); -	} -      } - -    } /* scan neighbors */ -     -  } /* scan addr list */ - +	struct listnode *addr_node; +	struct prefix *addr; +	struct pim_interface *pim_ifp; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	zassert(addr_list); + +	/* +	  Scan secondary address list +	*/ +	for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node, addr)) { +		struct listnode *neigh_node; +		struct pim_neighbor *neigh; + +		if (addr->family != AF_INET) +			continue; + +		/* +		  Scan neighbors +		*/ +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, +					  neigh_node, neigh)) { +			{ +				struct prefix *p = pim_neighbor_find_secondary( +					neigh, addr); +				if (p) { +					char addr_str[INET_ADDRSTRLEN]; +					char this_neigh_str[INET_ADDRSTRLEN]; +					char other_neigh_str[INET_ADDRSTRLEN]; + +					pim_inet4_dump( +						"<addr?>", addr->u.prefix4, +						addr_str, sizeof(addr_str)); +					pim_inet4_dump("<neigh1?>", neigh_addr, +						       this_neigh_str, +						       sizeof(this_neigh_str)); +					pim_inet4_dump("<neigh2?>", +						       neigh->source_addr, +						       other_neigh_str, +						       sizeof(other_neigh_str)); + +					zlog_info( +						"secondary addr %s recvd from neigh %s deleted from neigh %s on %s", +						addr_str, this_neigh_str, +						other_neigh_str, ifp->name); + +					listnode_delete(neigh->prefix_list, p); +					prefix_free(p); +				} +			} + +		} /* scan neighbors */ + +	} /* scan addr list */  }  void pim_neighbor_update(struct pim_neighbor *neigh, -			 pim_hello_options hello_options, -			 uint16_t holdtime, -			 uint32_t dr_priority, -			 struct list *addr_list) +			 pim_hello_options hello_options, uint16_t holdtime, +			 uint32_t dr_priority, struct list *addr_list)  { -  struct pim_interface *pim_ifp = neigh->interface->info; - -  /* Received holdtime ? */ -  if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { -    pim_neighbor_timer_reset(neigh, holdtime); -  } -  else { -    pim_neighbor_timer_reset(neigh, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); -  } +	struct pim_interface *pim_ifp = neigh->interface->info; + +	/* Received holdtime ? */ +	if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { +		pim_neighbor_timer_reset(neigh, holdtime); +	} else { +		pim_neighbor_timer_reset(neigh, +					 PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); +	}  #ifdef DUMP_PREFIX_LIST -  zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d", -	     __PRETTY_FUNCTION__, -	     (unsigned) neigh->prefix_list, -	     neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1, -	     (unsigned) addr_list, -	     addr_list ? (int) listcount(addr_list) : -1); +	zlog_debug( +		"%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d", +		__PRETTY_FUNCTION__, (unsigned)neigh->prefix_list, +		neigh->prefix_list ? (int)listcount(neigh->prefix_list) : -1, +		(unsigned)addr_list, +		addr_list ? (int)listcount(addr_list) : -1);  #endif -  if (neigh->prefix_list == addr_list) { -    if (addr_list) { -      zlog_err("%s: internal error: trying to replace same prefix list=%p", -	       __PRETTY_FUNCTION__, (void *) addr_list); -    } -  } -  else { -    /* Delete existing secondary address list */ -    delete_prefix_list(neigh); -  } - -  if (addr_list) { -    delete_from_neigh_addr(neigh->interface, addr_list, neigh->source_addr); -  } - -  /* Replace secondary address list */ -  neigh->prefix_list = addr_list; - -  update_dr_priority(neigh, -		     hello_options, -		     dr_priority); -  /* -    Copy flags -   */ -  neigh->hello_options = hello_options; +	if (neigh->prefix_list == addr_list) { +		if (addr_list) { +			zlog_err( +				"%s: internal error: trying to replace same prefix list=%p", +				__PRETTY_FUNCTION__, (void *)addr_list); +		} +	} else { +		/* Delete existing secondary address list */ +		delete_prefix_list(neigh); +	} + +	if (addr_list) { +		delete_from_neigh_addr(neigh->interface, addr_list, +				       neigh->source_addr); +	} + +	/* Replace secondary address list */ +	neigh->prefix_list = addr_list; + +	update_dr_priority(neigh, hello_options, dr_priority); +	/* +	  Copy flags +	 */ +	neigh->hello_options = hello_options;  } diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index eaaefd8fef..a4f2e10c88 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -29,54 +29,46 @@  #include "pim_tlv.h"  struct pim_neighbor { -  int64_t            creation; /* timestamp of creation */ -  struct in_addr     source_addr; -  pim_hello_options  hello_options; -  uint16_t           holdtime; -  uint16_t           propagation_delay_msec; -  uint16_t           override_interval_msec; -  uint32_t           dr_priority; -  uint32_t           generation_id; -  struct list       *prefix_list; /* list of struct prefix */ -  struct thread     *t_expire_timer; -  struct interface  *interface; +	int64_t creation; /* timestamp of creation */ +	struct in_addr source_addr; +	pim_hello_options hello_options; +	uint16_t holdtime; +	uint16_t propagation_delay_msec; +	uint16_t override_interval_msec; +	uint32_t dr_priority; +	uint32_t generation_id; +	struct list *prefix_list; /* list of struct prefix */ +	struct thread *t_expire_timer; +	struct interface *interface; -  struct thread     *jp_timer; -  struct list       *upstream_jp_agg; -  struct bfd_info   *bfd_info; +	struct thread *jp_timer; +	struct list *upstream_jp_agg; +	struct bfd_info *bfd_info;  };  void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime);  void pim_neighbor_free(struct pim_neighbor *neigh);  struct pim_neighbor *pim_neighbor_find(struct interface *ifp,  				       struct in_addr source_addr); -struct pim_neighbor *pim_neighbor_find_by_secondary (struct interface *ifp, -                                                     struct prefix *src); -struct pim_neighbor *pim_neighbor_find_if (struct interface *ifp); +struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp, +						    struct prefix *src); +struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp);  #define PIM_NEIGHBOR_SEND_DELAY 0  #define PIM_NEIGHBOR_SEND_NOW   1 -struct pim_neighbor *pim_neighbor_add(struct interface *ifp, -				      struct in_addr source_addr, -				      pim_hello_options hello_options, -				      uint16_t holdtime, -				      uint16_t propagation_delay, -				      uint16_t override_interval, -				      uint32_t dr_priority, -				      uint32_t generation_id, -				      struct list *addr_list, -				      int send_hello_now); -void pim_neighbor_delete(struct interface *ifp, -			 struct pim_neighbor *neigh, +struct pim_neighbor * +pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, +		 pim_hello_options hello_options, uint16_t holdtime, +		 uint16_t propagation_delay, uint16_t override_interval, +		 uint32_t dr_priority, uint32_t generation_id, +		 struct list *addr_list, int send_hello_now); +void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,  			 const char *delete_message); -void pim_neighbor_delete_all(struct interface *ifp, -			     const char *delete_message); +void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message);  void pim_neighbor_update(struct pim_neighbor *neigh, -			 pim_hello_options hello_options, -			 uint16_t holdtime, -			 uint32_t dr_priority, -			 struct list *addr_list); +			 pim_hello_options hello_options, uint16_t holdtime, +			 uint32_t dr_priority, struct list *addr_list);  struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,  					   struct prefix *addr);  int pim_if_dr_election(struct interface *ifp); diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 4aa6ecd5f3..f8bf2ac77c 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -44,258 +44,247 @@   * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister   *   command to Zebra.   */ -void -pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, -                       int command) +void pim_sendmsg_zebra_rnh(struct zclient *zclient, +			   struct pim_nexthop_cache *pnc, int command)  { -  struct stream *s; -  struct prefix *p; -  int ret; - -  /* Check socket. */ -  if (!zclient || zclient->sock < 0) -    return; - -  p = &(pnc->rpf.rpf_addr); -  s = zclient->obuf; -  stream_reset (s); -  zclient_create_header (s, command, VRF_DEFAULT); -  /* get update for all routes for a prefix */ -  stream_putc (s, 0); - -  stream_putw (s, PREFIX_FAMILY (p)); -  stream_putc (s, p->prefixlen); -  switch (PREFIX_FAMILY (p)) -    { -    case AF_INET: -      stream_put_in_addr (s, &p->u.prefix4); -      break; -    case AF_INET6: -      stream_put (s, &(p->u.prefix6), 16); -      break; -    default: -      break; -    } -  stream_putw_at (s, 0, stream_get_endp (s)); - -  ret = zclient_send_message (zclient); -  if (ret < 0) -    zlog_warn ("sendmsg_nexthop: zclient_send_message() failed"); - - -  if (PIM_DEBUG_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      prefix2str (p, buf, sizeof (buf)); -      zlog_debug ("%s: NHT %sregistered addr %s with Zebra ret:%d ", -                  __PRETTY_FUNCTION__, -                  (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", buf, ret); -    } - -  return; +	struct stream *s; +	struct prefix *p; +	int ret; + +	/* Check socket. */ +	if (!zclient || zclient->sock < 0) +		return; + +	p = &(pnc->rpf.rpf_addr); +	s = zclient->obuf; +	stream_reset(s); +	zclient_create_header(s, command, VRF_DEFAULT); +	/* get update for all routes for a prefix */ +	stream_putc(s, 0); + +	stream_putw(s, PREFIX_FAMILY(p)); +	stream_putc(s, p->prefixlen); +	switch (PREFIX_FAMILY(p)) { +	case AF_INET: +		stream_put_in_addr(s, &p->u.prefix4); +		break; +	case AF_INET6: +		stream_put(s, &(p->u.prefix6), 16); +		break; +	default: +		break; +	} +	stream_putw_at(s, 0, stream_get_endp(s)); + +	ret = zclient_send_message(zclient); +	if (ret < 0) +		zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); + + +	if (PIM_DEBUG_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		prefix2str(p, buf, sizeof(buf)); +		zlog_debug("%s: NHT %sregistered addr %s with Zebra ret:%d ", +			   __PRETTY_FUNCTION__, +			   (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", +			   buf, ret); +	} + +	return;  } -struct pim_nexthop_cache * -pim_nexthop_cache_find (struct pim_rpf *rpf) +struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf)  { -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_nexthop_cache lookup; +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_nexthop_cache lookup; -  lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; -  lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; -  lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; +	lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; +	lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; +	lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; -  pnc = hash_lookup (pimg->rpf_hash, &lookup); - -  return pnc; +	pnc = hash_lookup(pimg->rpf_hash, &lookup); +	return pnc;  } -struct pim_nexthop_cache * -pim_nexthop_cache_add (struct pim_rpf *rpf_addr) +struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr)  { -  struct pim_nexthop_cache *pnc; - -  pnc = XCALLOC (MTYPE_PIM_NEXTHOP_CACHE, sizeof (struct pim_nexthop_cache)); -  if (!pnc) -    { -      zlog_err ("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); -      return NULL; -    } -  pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; -  pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; -  pnc->rpf.rpf_addr.u.prefix4.s_addr = rpf_addr->rpf_addr.u.prefix4.s_addr; - -  pnc = hash_get (pimg->rpf_hash, pnc, hash_alloc_intern); - -  pnc->rp_list = list_new (); -  pnc->rp_list->cmp = pim_rp_list_cmp; - -  pnc->upstream_list = list_new (); -  pnc->upstream_list->cmp = pim_upstream_compare; - -  if (PIM_DEBUG_ZEBRA) -    { -      char rpf_str[PREFIX_STRLEN]; -      pim_addr_dump ("<nht?>", &rpf_addr->rpf_addr, rpf_str, -                     sizeof (rpf_str)); -      zlog_debug ("%s: NHT hash node, RP and UP lists allocated for %s ", -                  __PRETTY_FUNCTION__, rpf_str); -    } - -  return pnc; +	struct pim_nexthop_cache *pnc; + +	pnc = XCALLOC(MTYPE_PIM_NEXTHOP_CACHE, +		      sizeof(struct pim_nexthop_cache)); +	if (!pnc) { +		zlog_err("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); +		return NULL; +	} +	pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; +	pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; +	pnc->rpf.rpf_addr.u.prefix4.s_addr = +		rpf_addr->rpf_addr.u.prefix4.s_addr; + +	pnc = hash_get(pimg->rpf_hash, pnc, hash_alloc_intern); + +	pnc->rp_list = list_new(); +	pnc->rp_list->cmp = pim_rp_list_cmp; + +	pnc->upstream_list = list_new(); +	pnc->upstream_list->cmp = pim_upstream_compare; + +	if (PIM_DEBUG_ZEBRA) { +		char rpf_str[PREFIX_STRLEN]; +		pim_addr_dump("<nht?>", &rpf_addr->rpf_addr, rpf_str, +			      sizeof(rpf_str)); +		zlog_debug( +			"%s: NHT hash node, RP and UP lists allocated for %s ", +			__PRETTY_FUNCTION__, rpf_str); +	} + +	return pnc;  }  /* This API is used to Register an address with Zebra     ret 1 means nexthop cache is found.  */ -int -pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, -                           struct rp_info *rp, -                           struct pim_nexthop_cache *out_pnc) +int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up, +			      struct rp_info *rp, +			      struct pim_nexthop_cache *out_pnc)  { -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_rpf rpf; -  struct listnode *ch_node = NULL; -  struct zclient *zclient = NULL; - -  zclient = pim_zebra_zclient_get (); -  memset (&rpf, 0, sizeof (struct pim_rpf)); -  rpf.rpf_addr.family = addr->family; -  rpf.rpf_addr.prefixlen = addr->prefixlen; -  rpf.rpf_addr.u.prefix4 = addr->u.prefix4; - -  pnc = pim_nexthop_cache_find (&rpf); -  if (!pnc) -    { -      pnc = pim_nexthop_cache_add (&rpf); -      if (pnc) -        pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER); -      else -        { -          char rpf_str[PREFIX_STRLEN]; -          pim_addr_dump ("<nht-pnc?>", addr, rpf_str, sizeof (rpf_str)); -          zlog_warn ("%s: pnc node allocation failed. addr %s ", -                     __PRETTY_FUNCTION__, rpf_str); -          return -1; -        } -    } - -  if (rp != NULL) -    { -      ch_node = listnode_lookup (pnc->rp_list, rp); -      if (ch_node == NULL) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char rp_str[PREFIX_STRLEN]; -              pim_addr_dump ("<rp?>", &rp->rp.rpf_addr, rp_str, -                             sizeof (rp_str)); -              zlog_debug ("%s: Add RP %s node to pnc cached list", -                          __PRETTY_FUNCTION__, rp_str); -            } -          listnode_add_sort (pnc->rp_list, rp); -        } -    } - -  if (up != NULL) -    { -      ch_node = listnode_lookup (pnc->upstream_list, up); -      if (ch_node == NULL) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char buf[PREFIX2STR_BUFFER]; -              prefix2str (addr, buf, sizeof (buf)); -              zlog_debug ("%s: Add upstream %s node to pnc cached list, rpf %s", -                 __PRETTY_FUNCTION__, up->sg_str, buf); -            } -          listnode_add_sort (pnc->upstream_list, up); -        } -    } - -  if (pnc && CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID)) -    { -      memcpy (out_pnc, pnc, sizeof (struct pim_nexthop_cache)); -      return 1; -    } - -  return 0; +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_rpf rpf; +	struct listnode *ch_node = NULL; +	struct zclient *zclient = NULL; + +	zclient = pim_zebra_zclient_get(); +	memset(&rpf, 0, sizeof(struct pim_rpf)); +	rpf.rpf_addr.family = addr->family; +	rpf.rpf_addr.prefixlen = addr->prefixlen; +	rpf.rpf_addr.u.prefix4 = addr->u.prefix4; + +	pnc = pim_nexthop_cache_find(&rpf); +	if (!pnc) { +		pnc = pim_nexthop_cache_add(&rpf); +		if (pnc) +			pim_sendmsg_zebra_rnh(zclient, pnc, +					      ZEBRA_NEXTHOP_REGISTER); +		else { +			char rpf_str[PREFIX_STRLEN]; +			pim_addr_dump("<nht-pnc?>", addr, rpf_str, +				      sizeof(rpf_str)); +			zlog_warn("%s: pnc node allocation failed. addr %s ", +				  __PRETTY_FUNCTION__, rpf_str); +			return -1; +		} +	} + +	if (rp != NULL) { +		ch_node = listnode_lookup(pnc->rp_list, rp); +		if (ch_node == NULL) { +			if (PIM_DEBUG_ZEBRA) { +				char rp_str[PREFIX_STRLEN]; +				pim_addr_dump("<rp?>", &rp->rp.rpf_addr, rp_str, +					      sizeof(rp_str)); +				zlog_debug( +					"%s: Add RP %s node to pnc cached list", +					__PRETTY_FUNCTION__, rp_str); +			} +			listnode_add_sort(pnc->rp_list, rp); +		} +	} + +	if (up != NULL) { +		ch_node = listnode_lookup(pnc->upstream_list, up); +		if (ch_node == NULL) { +			if (PIM_DEBUG_ZEBRA) { +				char buf[PREFIX2STR_BUFFER]; +				prefix2str(addr, buf, sizeof(buf)); +				zlog_debug( +					"%s: Add upstream %s node to pnc cached list, rpf %s", +					__PRETTY_FUNCTION__, up->sg_str, buf); +			} +			listnode_add_sort(pnc->upstream_list, up); +		} +	} + +	if (pnc && CHECK_FLAG(pnc->flags, PIM_NEXTHOP_VALID)) { +		memcpy(out_pnc, pnc, sizeof(struct pim_nexthop_cache)); +		return 1; +	} + +	return 0;  } -void -pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, -                            struct rp_info *rp) +void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up, +				struct rp_info *rp)  { -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_nexthop_cache lookup; -  struct zclient *zclient = NULL; - -  zclient = pim_zebra_zclient_get (); - -  /* Remove from RPF hash if it is the last entry */ -  lookup.rpf.rpf_addr = *addr; -  pnc = hash_lookup (pimg->rpf_hash, &lookup); -  if (pnc) -    { -      if (rp) -        listnode_delete (pnc->rp_list, rp); -      if (up) -        listnode_delete (pnc->upstream_list, up); - -      if (PIM_DEBUG_ZEBRA) -        zlog_debug ("%s: NHT rp_list count:%d upstream_list count:%d ", -                    __PRETTY_FUNCTION__, pnc->rp_list->count, -                    pnc->upstream_list->count); - -      if (pnc->rp_list->count == 0 && pnc->upstream_list->count == 0) -        { -          pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_UNREGISTER); - -          list_delete (pnc->rp_list); -          list_delete (pnc->upstream_list); - -          hash_release (pimg->rpf_hash, pnc); -          if (pnc->nexthop) -            nexthops_free (pnc->nexthop); -          XFREE (MTYPE_PIM_NEXTHOP_CACHE, pnc); -        } -    } +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_nexthop_cache lookup; +	struct zclient *zclient = NULL; + +	zclient = pim_zebra_zclient_get(); + +	/* Remove from RPF hash if it is the last entry */ +	lookup.rpf.rpf_addr = *addr; +	pnc = hash_lookup(pimg->rpf_hash, &lookup); +	if (pnc) { +		if (rp) +			listnode_delete(pnc->rp_list, rp); +		if (up) +			listnode_delete(pnc->upstream_list, up); + +		if (PIM_DEBUG_ZEBRA) +			zlog_debug( +				"%s: NHT rp_list count:%d upstream_list count:%d ", +				__PRETTY_FUNCTION__, pnc->rp_list->count, +				pnc->upstream_list->count); + +		if (pnc->rp_list->count == 0 +		    && pnc->upstream_list->count == 0) { +			pim_sendmsg_zebra_rnh(zclient, pnc, +					      ZEBRA_NEXTHOP_UNREGISTER); + +			list_delete(pnc->rp_list); +			list_delete(pnc->upstream_list); + +			hash_release(pimg->rpf_hash, pnc); +			if (pnc->nexthop) +				nexthops_free(pnc->nexthop); +			XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc); +		} +	}  }  /* Update RP nexthop info based on Nexthop update received from Zebra.*/ -int -pim_update_rp_nh (struct pim_nexthop_cache *pnc) +int pim_update_rp_nh(struct pim_nexthop_cache *pnc)  { -  struct listnode *node = NULL; -  struct rp_info *rp_info = NULL; -  int ret = 0; - -  /*Traverse RP list and update each RP Nexthop info */ -  for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info)) -    { -      if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) -        continue; - -      //Compute PIM RPF using cached nexthop -      ret = pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop, -                           &rp_info->rp.rpf_addr, &rp_info->group, 1); - -      if (PIM_DEBUG_TRACE) -        { -          char rp_str[PREFIX_STRLEN]; -          pim_addr_dump ("<rp?>", &rp_info->rp.rpf_addr, rp_str, -                         sizeof (rp_str)); -          zlog_debug ("%s: NHT update, nexthop for RP %s is interface %s ", -                      __PRETTY_FUNCTION__, rp_str, -                      rp_info->rp.source_nexthop.interface->name); -        } -    } - -  if (ret) -    return 0; - -  return 1; +	struct listnode *node = NULL; +	struct rp_info *rp_info = NULL; +	int ret = 0; + +	/*Traverse RP list and update each RP Nexthop info */ +	for (ALL_LIST_ELEMENTS_RO(pnc->rp_list, node, rp_info)) { +		if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) +			continue; + +		// Compute PIM RPF using cached nexthop +		ret = pim_ecmp_nexthop_search(pnc, &rp_info->rp.source_nexthop, +					      &rp_info->rp.rpf_addr, +					      &rp_info->group, 1); + +		if (PIM_DEBUG_TRACE) { +			char rp_str[PREFIX_STRLEN]; +			pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp_str, +				      sizeof(rp_str)); +			zlog_debug( +				"%s: NHT update, nexthop for RP %s is interface %s ", +				__PRETTY_FUNCTION__, rp_str, +				rp_info->rp.source_nexthop.interface->name); +		} +	} + +	if (ret) +		return 0; + +	return 1;  }  /* This API is used to traverse nexthop cache of RPF addr @@ -303,771 +292,779 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)     unresolved state and due to event like pim neighbor     UP event if it can be resolved.  */ -void -pim_resolve_upstream_nh (struct prefix *nht_p) +void pim_resolve_upstream_nh(struct prefix *nht_p)  { -  struct nexthop *nh_node = NULL; -  struct pim_nexthop_cache pnc; -  struct pim_neighbor *nbr = NULL; - -  memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -  if ((pim_find_or_track_nexthop (nht_p, NULL, NULL, &pnc)) == 1) -    { -      for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) -        { -          if (nh_node->gate.ipv4.s_addr == 0) -            { -              struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex, -                                                             VRF_DEFAULT); -              nbr = pim_neighbor_find_if (ifp1); -              if (nbr) -                { -                  nh_node->gate.ipv4 = nbr->source_addr; -                  if (PIM_DEBUG_TRACE) -                    { -                      char str[PREFIX_STRLEN]; -                      char str1[INET_ADDRSTRLEN]; -                      pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str1, -                                      sizeof (str1)); -                      pim_addr_dump ("<nht_addr?>", nht_p, str, sizeof (str)); -                      zlog_debug ("%s: addr %s new nexthop addr %s interface %s", -                              __PRETTY_FUNCTION__, str, str1, ifp1->name); -                    } -                } -            } -        } -    } +	struct nexthop *nh_node = NULL; +	struct pim_nexthop_cache pnc; +	struct pim_neighbor *nbr = NULL; + +	memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +	if ((pim_find_or_track_nexthop(nht_p, NULL, NULL, &pnc)) == 1) { +		for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) { +			if (nh_node->gate.ipv4.s_addr == 0) { +				struct interface *ifp1 = if_lookup_by_index( +					nh_node->ifindex, VRF_DEFAULT); +				nbr = pim_neighbor_find_if(ifp1); +				if (nbr) { +					nh_node->gate.ipv4 = nbr->source_addr; +					if (PIM_DEBUG_TRACE) { +						char str[PREFIX_STRLEN]; +						char str1[INET_ADDRSTRLEN]; +						pim_inet4_dump("<nht_nbr?>", +							       nbr->source_addr, +							       str1, +							       sizeof(str1)); +						pim_addr_dump("<nht_addr?>", +							      nht_p, str, +							      sizeof(str)); +						zlog_debug( +							"%s: addr %s new nexthop addr %s interface %s", +							__PRETTY_FUNCTION__, +							str, str1, ifp1->name); +					} +				} +			} +		} +	}  }  /* Update Upstream nexthop info based on Nexthop update received from Zebra.*/ -static int -pim_update_upstream_nh (struct pim_nexthop_cache *pnc) +static int pim_update_upstream_nh(struct pim_nexthop_cache *pnc)  { -  struct listnode     *up_node; -  struct listnode     *ifnode; -  struct listnode     *up_nextnode; -  struct listnode     *node; -  struct pim_upstream *up = NULL; -  struct interface    *ifp = NULL; -  int                 vif_index = 0; - -  for (ALL_LIST_ELEMENTS (pnc->upstream_list, up_node, up_nextnode, up)) -    { -      enum pim_rpf_result rpf_result; -      struct pim_rpf old; - -      old.source_nexthop.interface = up->rpf.source_nexthop.interface; -      rpf_result = pim_rpf_update (up, &old, 0); -      if (rpf_result == PIM_RPF_FAILURE) -        continue; - -      /* update kernel multicast forwarding cache (MFC) */ -      if (up->channel_oil) -        { -          ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex; -          vif_index = pim_if_find_vifindex_by_ifindex (ifindex); -          /* Pass Current selected NH vif index to mroute download */ -          if (vif_index) -            pim_scan_individual_oil (up->channel_oil, vif_index); -          else -            { -              if (PIM_DEBUG_ZEBRA) -                zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", -                   __PRETTY_FUNCTION__, up->sg_str, -                   up->rpf.source_nexthop.interface->name); -            } -        } - -      if (rpf_result == PIM_RPF_CHANGED) -        { -          struct pim_neighbor *nbr; - -          nbr = pim_neighbor_find (old.source_nexthop.interface, -                                   old.rpf_addr.u.prefix4); -          if (nbr) -            pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - -          /* -           * We have detected a case where we might need to rescan -           * the inherited o_list so do it. -           */ -          if (up->channel_oil && up->channel_oil->oil_inherited_rescan) -            { -              pim_upstream_inherited_olist_decide (up); -              up->channel_oil->oil_inherited_rescan = 0; -            } - -          if (up->join_state == PIM_UPSTREAM_JOINED) -            { -              /* -               * If we come up real fast we can be here -               * where the mroute has not been installed -               * so install it. -               */ -              if (up->channel_oil && !up->channel_oil->installed) -                pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - -              /* -                 RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Messages - -                 Transitions from Joined State - -                 RPF'(S,G) changes not due to an Assert - -                 The upstream (S,G) state machine remains in Joined -                 state. Send Join(S,G) to the new upstream neighbor, which is -                 the new value of RPF'(S,G).  Send Prune(S,G) to the old -                 upstream neighbor, which is the old value of RPF'(S,G).  Set -                 the Join Timer (JT) to expire after t_periodic seconds. -               */ -              pim_jp_agg_switch_interface (&old, &up->rpf, up); - -              pim_upstream_join_timer_restart (up, &old); -            }                   /* up->join_state == PIM_UPSTREAM_JOINED */ - -          /* FIXME can join_desired actually be changed by pim_rpf_update() -             returning PIM_RPF_CHANGED ? */ -          pim_upstream_update_join_desired (up); - -        }                       /* PIM_RPF_CHANGED */ - -      if (PIM_DEBUG_TRACE) -        { -          zlog_debug ("%s: NHT upstream %s old ifp %s new ifp %s", -                      __PRETTY_FUNCTION__, up->sg_str, -                      old.source_nexthop.interface->name, -                      up->rpf.source_nexthop.interface->name); -        } -    }                           /* for (pnc->upstream_list) */ - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) -    if (ifp->info) -      { -        struct pim_interface *pim_ifp = ifp->info; -        struct pim_iface_upstream_switch *us; - -        for (ALL_LIST_ELEMENTS_RO (pim_ifp->upstream_switch_list, node, us)) -          { -            struct pim_rpf rpf; -            rpf.source_nexthop.interface = ifp; -            rpf.rpf_addr.u.prefix4 = us->address; -            pim_joinprune_send (&rpf, us->us); -            pim_jp_agg_clear_group (us->us); -          } -      } - -  return 0; +	struct listnode *up_node; +	struct listnode *ifnode; +	struct listnode *up_nextnode; +	struct listnode *node; +	struct pim_upstream *up = NULL; +	struct interface *ifp = NULL; +	int vif_index = 0; + +	for (ALL_LIST_ELEMENTS(pnc->upstream_list, up_node, up_nextnode, up)) { +		enum pim_rpf_result rpf_result; +		struct pim_rpf old; + +		old.source_nexthop.interface = up->rpf.source_nexthop.interface; +		rpf_result = pim_rpf_update(up, &old, 0); +		if (rpf_result == PIM_RPF_FAILURE) +			continue; + +		/* update kernel multicast forwarding cache (MFC) */ +		if (up->channel_oil) { +			ifindex_t ifindex = +				up->rpf.source_nexthop.interface->ifindex; +			vif_index = pim_if_find_vifindex_by_ifindex(ifindex); +			/* Pass Current selected NH vif index to mroute download +			 */ +			if (vif_index) +				pim_scan_individual_oil(up->channel_oil, +							vif_index); +			else { +				if (PIM_DEBUG_ZEBRA) +					zlog_debug( +						"%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", +						__PRETTY_FUNCTION__, up->sg_str, +						up->rpf.source_nexthop +							.interface->name); +			} +		} + +		if (rpf_result == PIM_RPF_CHANGED) { +			struct pim_neighbor *nbr; + +			nbr = pim_neighbor_find(old.source_nexthop.interface, +						old.rpf_addr.u.prefix4); +			if (nbr) +				pim_jp_agg_remove_group(nbr->upstream_jp_agg, +							up); + +			/* +			 * We have detected a case where we might need to rescan +			 * the inherited o_list so do it. +			 */ +			if (up->channel_oil +			    && up->channel_oil->oil_inherited_rescan) { +				pim_upstream_inherited_olist_decide(up); +				up->channel_oil->oil_inherited_rescan = 0; +			} + +			if (up->join_state == PIM_UPSTREAM_JOINED) { +				/* +				 * If we come up real fast we can be here +				 * where the mroute has not been installed +				 * so install it. +				 */ +				if (up->channel_oil +				    && !up->channel_oil->installed) +					pim_mroute_add(up->channel_oil, +						       __PRETTY_FUNCTION__); + +				/* +				   RFC 4601: 4.5.7.  Sending (S,G) Join/Prune +				   Messages + +				   Transitions from Joined State + +				   RPF'(S,G) changes not due to an Assert + +				   The upstream (S,G) state machine remains in +				   Joined +				   state. Send Join(S,G) to the new upstream +				   neighbor, which is +				   the new value of RPF'(S,G).  Send Prune(S,G) +				   to the old +				   upstream neighbor, which is the old value of +				   RPF'(S,G).  Set +				   the Join Timer (JT) to expire after +				   t_periodic seconds. +				 */ +				pim_jp_agg_switch_interface(&old, &up->rpf, up); + +				pim_upstream_join_timer_restart(up, &old); +			} /* up->join_state == PIM_UPSTREAM_JOINED */ + +			/* FIXME can join_desired actually be changed by +			   pim_rpf_update() +			   returning PIM_RPF_CHANGED ? */ +			pim_upstream_update_join_desired(up); + +		} /* PIM_RPF_CHANGED */ + +		if (PIM_DEBUG_TRACE) { +			zlog_debug("%s: NHT upstream %s old ifp %s new ifp %s", +				   __PRETTY_FUNCTION__, up->sg_str, +				   old.source_nexthop.interface->name, +				   up->rpf.source_nexthop.interface->name); +		} +	} /* for (pnc->upstream_list) */ + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) +		if (ifp->info) { +			struct pim_interface *pim_ifp = ifp->info; +			struct pim_iface_upstream_switch *us; + +			for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, +						  node, us)) { +				struct pim_rpf rpf; +				rpf.source_nexthop.interface = ifp; +				rpf.rpf_addr.u.prefix4 = us->address; +				pim_joinprune_send(&rpf, us->us); +				pim_jp_agg_clear_group(us->us); +			} +		} + +	return 0;  } -uint32_t -pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp) +uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp)  { -  uint32_t hash_val; -  uint32_t s = 0, g = 0; - -  if ((!src)) -    return 0; - -  switch (src->family) -    { -    case AF_INET: -      { -        s = src->u.prefix4.s_addr; -        s = s == 0 ? 1 : s; -        if (grp) -          g = grp->u.prefix4.s_addr; -      } -      break; -    default: -      break; -    } - -  hash_val = jhash_2words (g, s, 101); -  if (PIM_DEBUG_PIM_TRACE_DETAIL) -    { -      char buf[PREFIX2STR_BUFFER]; -      char bufg[PREFIX2STR_BUFFER]; -      prefix2str (src, buf, sizeof (buf)); -      if (grp) -        prefix2str (grp, bufg, sizeof (bufg)); -      zlog_debug ("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, buf, -                  grp ? bufg : "", hash_val); - -    } -  return hash_val; +	uint32_t hash_val; +	uint32_t s = 0, g = 0; + +	if ((!src)) +		return 0; + +	switch (src->family) { +	case AF_INET: { +		s = src->u.prefix4.s_addr; +		s = s == 0 ? 1 : s; +		if (grp) +			g = grp->u.prefix4.s_addr; +	} break; +	default: +		break; +	} + +	hash_val = jhash_2words(g, s, 101); +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		char buf[PREFIX2STR_BUFFER]; +		char bufg[PREFIX2STR_BUFFER]; +		prefix2str(src, buf, sizeof(buf)); +		if (grp) +			prefix2str(grp, bufg, sizeof(bufg)); +		zlog_debug("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, +			   buf, grp ? bufg : "", hash_val); +	} +	return hash_val;  } -int -pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc, -                         struct pim_nexthop *nexthop, struct prefix *src, -                         struct prefix *grp, int neighbor_needed) +int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc, +			    struct pim_nexthop *nexthop, struct prefix *src, +			    struct prefix *grp, int neighbor_needed)  { -  struct pim_neighbor *nbr = NULL; -  struct nexthop *nh_node = NULL; -  ifindex_t first_ifindex; -  struct interface *ifp = NULL; -  uint32_t hash_val = 0, mod_val = 0; -  uint8_t nh_iter = 0, found = 0; - -  if (!pnc || !pnc->nexthop_num || !nexthop) -    return -1; - -  //Current Nexthop is VALID, check to stay on the current path. -  if (nexthop->interface && nexthop->interface->info && -      nexthop->mrib_nexthop_addr.u.prefix4.s_addr != -      PIM_NET_INADDR_ANY) -    { -      /* User configured knob to explicitly switch -         to new path is disabled or current path -         metric is less than nexthop update. -       */ - -      if (qpim_ecmp_rebalance_enable == 0) -        { -          uint8_t curr_route_valid = 0; -          //Check if current nexthop is present in new updated Nexthop list. -          //If the current nexthop is not valid, candidate to choose new Nexthop. -          for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) -            curr_route_valid = (nexthop->interface->ifindex == nh_node->ifindex); - -          if (curr_route_valid && -              !pim_if_connected_to_source (nexthop->interface, -                                           src->u.prefix4)) -            { -              nbr = pim_neighbor_find (nexthop->interface, -                                       nexthop->mrib_nexthop_addr.u.prefix4); -              if (!nbr && !if_is_loopback (nexthop->interface)) -                { -                  if (PIM_DEBUG_TRACE) -                    zlog_debug ("%s: current nexthop does not have nbr ", -                                __PRETTY_FUNCTION__); -                } -              else -                { -                  if (PIM_DEBUG_TRACE) -                    { -                      char src_str[INET_ADDRSTRLEN]; -                      pim_inet4_dump ("<addr?>", src->u.prefix4, src_str, -                                      sizeof (src_str)); -                      char grp_str[INET_ADDRSTRLEN]; -                      pim_inet4_dump ("<addr?>", grp->u.prefix4, grp_str, -                                      sizeof (grp_str)); -                      zlog_debug ("%s: (%s, %s) current nexthop %s is valid, skipping new path selection", -                         __PRETTY_FUNCTION__, src_str, grp_str, -                         nexthop->interface->name); -                    } -                  return 0; -                } -            } -        } -    } -  if (qpim_ecmp_enable) -    { -      //PIM ECMP flag is enable then choose ECMP path. -      hash_val = pim_compute_ecmp_hash (src, grp); -      mod_val = hash_val % pnc->nexthop_num; -      if (PIM_DEBUG_PIM_TRACE_DETAIL) -        zlog_debug ("%s: hash_val %u mod_val %u ", -                    __PRETTY_FUNCTION__, hash_val, mod_val); -    } - -  for (nh_node = pnc->nexthop; nh_node && (found == 0); -       nh_node = nh_node->next) -    { -      first_ifindex = nh_node->ifindex; -      ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); -      if (!ifp) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, -                              sizeof (addr_str)); -              zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", -                 __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); -            } -          if (nh_iter == mod_val) -            mod_val++;          //Select nexthpath -          nh_iter++; -          continue; -        } -      if (!ifp->info) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", src->u.prefix4, addr_str, -                              sizeof (addr_str)); -              zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", -                 __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); -            } -          if (nh_iter == mod_val) -            mod_val++;          //Select nexthpath -          nh_iter++; -          continue; -        } - -      if (neighbor_needed -          && !pim_if_connected_to_source (ifp, src->u.prefix4)) -        { -          nbr = pim_neighbor_find (ifp, nh_node->gate.ipv4); -          if (PIM_DEBUG_PIM_TRACE_DETAIL) -            zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); -          if (!nbr && !if_is_loopback (ifp)) -            { -              if (PIM_DEBUG_ZEBRA) -                zlog_debug ("%s: pim nbr not found on input interface %s", -                            __PRETTY_FUNCTION__, ifp->name); -              if (nh_iter == mod_val) -                mod_val++;      //Select nexthpath -              nh_iter++; -              continue; -            } -        } - -      if (nh_iter == mod_val) -        { -          nexthop->interface                    = ifp; -          nexthop->mrib_nexthop_addr.family     = AF_INET; -          nexthop->mrib_nexthop_addr.prefixlen  = IPV4_MAX_BITLEN; -          nexthop->mrib_nexthop_addr.u.prefix4  = nh_node->gate.ipv4; -          nexthop->mrib_metric_preference       = pnc->distance; -          nexthop->mrib_route_metric            = pnc->metric; -          nexthop->last_lookup                  = src->u.prefix4; -          nexthop->last_lookup_time             = pim_time_monotonic_usec (); -          nexthop->nbr                          = nbr; -          found                                 = 1; -          if (PIM_DEBUG_ZEBRA) -            { -              char buf[INET_ADDRSTRLEN]; -              char buf2[INET_ADDRSTRLEN]; -              char buf3[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<src?>", src->u.prefix4, buf2, sizeof (buf2)); -              pim_inet4_dump ("<grp?>", grp->u.prefix4, buf3, sizeof (buf3)); -              pim_inet4_dump ("<rpf?>", -                              nexthop->mrib_nexthop_addr.u.prefix4, buf, -                              sizeof (buf)); -              zlog_debug ("%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", -                          __PRETTY_FUNCTION__, buf2, buf3, ifp->name, -                          buf, mod_val, nh_iter, qpim_ecmp_enable); -            } -        } -      nh_iter++; -    } - -  if (found) -    return 0; -  else -    return -1; +	struct pim_neighbor *nbr = NULL; +	struct nexthop *nh_node = NULL; +	ifindex_t first_ifindex; +	struct interface *ifp = NULL; +	uint32_t hash_val = 0, mod_val = 0; +	uint8_t nh_iter = 0, found = 0; + +	if (!pnc || !pnc->nexthop_num || !nexthop) +		return -1; + +	// Current Nexthop is VALID, check to stay on the current path. +	if (nexthop->interface && nexthop->interface->info +	    && nexthop->mrib_nexthop_addr.u.prefix4.s_addr +		       != PIM_NET_INADDR_ANY) { +		/* User configured knob to explicitly switch +		   to new path is disabled or current path +		   metric is less than nexthop update. +		 */ + +		if (qpim_ecmp_rebalance_enable == 0) { +			uint8_t curr_route_valid = 0; +			// Check if current nexthop is present in new updated +			// Nexthop list. +			// If the current nexthop is not valid, candidate to +			// choose new Nexthop. +			for (nh_node = pnc->nexthop; nh_node; +			     nh_node = nh_node->next) +				curr_route_valid = (nexthop->interface->ifindex +						    == nh_node->ifindex); + +			if (curr_route_valid +			    && !pim_if_connected_to_source(nexthop->interface, +							   src->u.prefix4)) { +				nbr = pim_neighbor_find( +					nexthop->interface, +					nexthop->mrib_nexthop_addr.u.prefix4); +				if (!nbr +				    && !if_is_loopback(nexthop->interface)) { +					if (PIM_DEBUG_TRACE) +						zlog_debug( +							"%s: current nexthop does not have nbr ", +							__PRETTY_FUNCTION__); +				} else { +					if (PIM_DEBUG_TRACE) { +						char src_str[INET_ADDRSTRLEN]; +						pim_inet4_dump("<addr?>", +							       src->u.prefix4, +							       src_str, +							       sizeof(src_str)); +						char grp_str[INET_ADDRSTRLEN]; +						pim_inet4_dump("<addr?>", +							       grp->u.prefix4, +							       grp_str, +							       sizeof(grp_str)); +						zlog_debug( +							"%s: (%s, %s) current nexthop %s is valid, skipping new path selection", +							__PRETTY_FUNCTION__, +							src_str, grp_str, +							nexthop->interface->name); +					} +					return 0; +				} +			} +		} +	} +	if (qpim_ecmp_enable) { +		// PIM ECMP flag is enable then choose ECMP path. +		hash_val = pim_compute_ecmp_hash(src, grp); +		mod_val = hash_val % pnc->nexthop_num; +		if (PIM_DEBUG_PIM_TRACE_DETAIL) +			zlog_debug("%s: hash_val %u mod_val %u ", +				   __PRETTY_FUNCTION__, hash_val, mod_val); +	} + +	for (nh_node = pnc->nexthop; nh_node && (found == 0); +	     nh_node = nh_node->next) { +		first_ifindex = nh_node->ifindex; +		ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); +		if (!ifp) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", src->u.prefix4, +					       addr_str, sizeof(addr_str)); +				zlog_debug( +					"%s %s: could not find interface for ifindex %d (address %s)", +					__FILE__, __PRETTY_FUNCTION__, +					first_ifindex, addr_str); +			} +			if (nh_iter == mod_val) +				mod_val++; // Select nexthpath +			nh_iter++; +			continue; +		} +		if (!ifp->info) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", src->u.prefix4, +					       addr_str, sizeof(addr_str)); +				zlog_debug( +					"%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", +					__PRETTY_FUNCTION__, ifp->name, +					first_ifindex, addr_str); +			} +			if (nh_iter == mod_val) +				mod_val++; // Select nexthpath +			nh_iter++; +			continue; +		} + +		if (neighbor_needed +		    && !pim_if_connected_to_source(ifp, src->u.prefix4)) { +			nbr = pim_neighbor_find(ifp, nh_node->gate.ipv4); +			if (PIM_DEBUG_PIM_TRACE_DETAIL) +				zlog_debug("ifp name: %s, pim nbr: %p", +					   ifp->name, nbr); +			if (!nbr && !if_is_loopback(ifp)) { +				if (PIM_DEBUG_ZEBRA) +					zlog_debug( +						"%s: pim nbr not found on input interface %s", +						__PRETTY_FUNCTION__, ifp->name); +				if (nh_iter == mod_val) +					mod_val++; // Select nexthpath +				nh_iter++; +				continue; +			} +		} + +		if (nh_iter == mod_val) { +			nexthop->interface = ifp; +			nexthop->mrib_nexthop_addr.family = AF_INET; +			nexthop->mrib_nexthop_addr.prefixlen = IPV4_MAX_BITLEN; +			nexthop->mrib_nexthop_addr.u.prefix4 = +				nh_node->gate.ipv4; +			nexthop->mrib_metric_preference = pnc->distance; +			nexthop->mrib_route_metric = pnc->metric; +			nexthop->last_lookup = src->u.prefix4; +			nexthop->last_lookup_time = pim_time_monotonic_usec(); +			nexthop->nbr = nbr; +			found = 1; +			if (PIM_DEBUG_ZEBRA) { +				char buf[INET_ADDRSTRLEN]; +				char buf2[INET_ADDRSTRLEN]; +				char buf3[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src->u.prefix4, buf2, +					       sizeof(buf2)); +				pim_inet4_dump("<grp?>", grp->u.prefix4, buf3, +					       sizeof(buf3)); +				pim_inet4_dump( +					"<rpf?>", +					nexthop->mrib_nexthop_addr.u.prefix4, +					buf, sizeof(buf)); +				zlog_debug( +					"%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", +					__PRETTY_FUNCTION__, buf2, buf3, +					ifp->name, buf, mod_val, nh_iter, +					qpim_ecmp_enable); +			} +		} +		nh_iter++; +	} + +	if (found) +		return 0; +	else +		return -1;  } -/* This API is used to parse Registered address nexthop update coming from Zebra */ -int -pim_parse_nexthop_update (int command, struct zclient *zclient, -                          zebra_size_t length, vrf_id_t vrf_id) +/* This API is used to parse Registered address nexthop update coming from Zebra + */ +int pim_parse_nexthop_update(int command, struct zclient *zclient, +			     zebra_size_t length, vrf_id_t vrf_id)  { -  struct stream *s; -  struct prefix p; -  struct nexthop *nexthop; -  struct nexthop *nhlist_head = NULL; -  struct nexthop *nhlist_tail = NULL; -  uint32_t metric, distance; -  u_char nexthop_num = 0; -  int i; -  struct pim_rpf rpf; -  struct pim_nexthop_cache *pnc = NULL; -  struct pim_neighbor *nbr = NULL; -  struct interface *ifp = NULL; -  struct interface *ifp1 = NULL; -  struct pim_interface *pim_ifp = NULL; -  char str[INET_ADDRSTRLEN]; - -  s = zclient->ibuf; -  memset (&p, 0, sizeof (struct prefix)); -  p.family = stream_getw (s); -  p.prefixlen = stream_getc (s); -  switch (p.family) -    { -    case AF_INET: -      p.u.prefix4.s_addr = stream_get_ipv4 (s); -      break; -    case AF_INET6: -      stream_get (&p.u.prefix6, s, 16); -      break; -    default: -      break; -    } - -  if (command == ZEBRA_NEXTHOP_UPDATE) -    { -      rpf.rpf_addr.family = p.family; -      rpf.rpf_addr.prefixlen = p.prefixlen; -      rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; -      pnc = pim_nexthop_cache_find (&rpf); -      if (!pnc) -        { -          if (PIM_DEBUG_TRACE) -            { -              char buf[PREFIX2STR_BUFFER]; -              prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); -              zlog_debug ("%s: Skipping NHT update, addr %s is not in local cached DB.", -                 __PRETTY_FUNCTION__, buf); -            } -          return 0; -        } -    } -  else -    { -      /* -       * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE -       */ -      return 0; -    } - -  pnc->last_update = pim_time_monotonic_usec (); -  distance = stream_getc (s); -  metric = stream_getl (s); -  nexthop_num = stream_getc (s); - -  if (nexthop_num) -    { -      pnc->nexthop_num = 0;     //Only increment for pim enabled rpf. - -      for (i = 0; i < nexthop_num; i++) -        { -          nexthop = nexthop_new (); -          nexthop->type = stream_getc (s); -          switch (nexthop->type) -            { -            case NEXTHOP_TYPE_IPV4: -              nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); -              nexthop->ifindex = stream_getl (s); -              break; -            case NEXTHOP_TYPE_IFINDEX: -              nexthop->ifindex = stream_getl (s); -              break; -            case NEXTHOP_TYPE_IPV4_IFINDEX: -              nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); -              nexthop->ifindex = stream_getl (s); -              break; -            case NEXTHOP_TYPE_IPV6: -              stream_get (&nexthop->gate.ipv6, s, 16); -              break; -            case NEXTHOP_TYPE_IPV6_IFINDEX: -              stream_get (&nexthop->gate.ipv6, s, 16); -              nexthop->ifindex = stream_getl (s); -              ifp1 = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); -              nbr = pim_neighbor_find_if (ifp1); -              /* Overwrite with Nbr address as NH addr */ -              if (nbr) -                { -                  nexthop->gate.ipv4 = nbr->source_addr; -                  if (PIM_DEBUG_TRACE) -                    { -                      pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, str, -                                      sizeof (str)); -                      zlog_debug ("%s: NHT using pim nbr addr %s interface %s as rpf", -                                  __PRETTY_FUNCTION__, str, ifp1->name); -                    } -                } -              else -                { -                  if (PIM_DEBUG_TRACE) -                    { -                      pim_ifp = ifp1->info; -                      zlog_debug ("%s: NHT pim nbr not found on interface %s nbr count:%d ", -                                  __PRETTY_FUNCTION__, ifp1->name, -                                  pim_ifp->pim_neighbor_list->count); -                    } -                  //Mark nexthop address to 0 until PIM Nbr is resolved. -                  nexthop->gate.ipv4.s_addr = PIM_NET_INADDR_ANY; -                } - -              break; -            default: -              /* do nothing */ -              break; -            } - -          if (PIM_DEBUG_TRACE) -            { -              char p_str[PREFIX2STR_BUFFER]; -              prefix2str (&p, p_str, sizeof (p_str)); -              zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", -                 __PRETTY_FUNCTION__, p_str, i + 1, -                 inet_ntoa (nexthop->gate.ipv4), nexthop->type, distance, -                 metric); -            } - -          ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); -          if (!ifp) -            { -              if (PIM_DEBUG_ZEBRA) -                { -                  char buf[NEXTHOP_STRLEN]; -                  zlog_debug ("%s: could not find interface for ifindex %d (addr %s)", -                     __PRETTY_FUNCTION__, nexthop->ifindex, -                     nexthop2str (nexthop, buf, sizeof (buf))); -                } -              nexthop_free (nexthop); -              continue; -            } - -          if (!ifp->info) -            { -              if (PIM_DEBUG_ZEBRA) -                { -                  char buf[NEXTHOP_STRLEN]; -                  zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", -                     __PRETTY_FUNCTION__, ifp->name, nexthop->ifindex, -                     nexthop2str (nexthop, buf, sizeof (buf))); -                } -              nexthop_free (nexthop); -              continue; -            } - -          if (nhlist_tail) -            { -              nhlist_tail->next = nexthop; -              nhlist_tail = nexthop; -            } -          else -            { -              nhlist_tail = nexthop; -              nhlist_head = nexthop; -            } -          //Only keep track of nexthops which are PIM enabled. -          pnc->nexthop_num++; -        } -      /* Reset existing pnc->nexthop before assigning new list */ -      nexthops_free (pnc->nexthop); -      pnc->nexthop = nhlist_head; -      if (pnc->nexthop_num) -        { -          pnc->flags |= PIM_NEXTHOP_VALID; -          pnc->distance = distance; -          pnc->metric = metric; -        } -    } -  else -    { -      pnc->flags &= ~PIM_NEXTHOP_VALID; -      pnc->nexthop_num = nexthop_num; -      nexthops_free (pnc->nexthop); -      pnc->nexthop = NULL; -    } - -  if (PIM_DEBUG_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      prefix2str (&p, buf, sizeof (buf)); -      zlog_debug ("%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", -         __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id, -         listcount (pnc->upstream_list), listcount (pnc->rp_list)); -    } - -  pim_rpf_set_refresh_time (); - -  if (listcount (pnc->rp_list)) -    pim_update_rp_nh (pnc); -  if (listcount (pnc->upstream_list)) -    pim_update_upstream_nh (pnc); - -  return 0; +	struct stream *s; +	struct prefix p; +	struct nexthop *nexthop; +	struct nexthop *nhlist_head = NULL; +	struct nexthop *nhlist_tail = NULL; +	uint32_t metric, distance; +	u_char nexthop_num = 0; +	int i; +	struct pim_rpf rpf; +	struct pim_nexthop_cache *pnc = NULL; +	struct pim_neighbor *nbr = NULL; +	struct interface *ifp = NULL; +	struct interface *ifp1 = NULL; +	struct pim_interface *pim_ifp = NULL; +	char str[INET_ADDRSTRLEN]; + +	s = zclient->ibuf; +	memset(&p, 0, sizeof(struct prefix)); +	p.family = stream_getw(s); +	p.prefixlen = stream_getc(s); +	switch (p.family) { +	case AF_INET: +		p.u.prefix4.s_addr = stream_get_ipv4(s); +		break; +	case AF_INET6: +		stream_get(&p.u.prefix6, s, 16); +		break; +	default: +		break; +	} + +	if (command == ZEBRA_NEXTHOP_UPDATE) { +		rpf.rpf_addr.family = p.family; +		rpf.rpf_addr.prefixlen = p.prefixlen; +		rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; +		pnc = pim_nexthop_cache_find(&rpf); +		if (!pnc) { +			if (PIM_DEBUG_TRACE) { +				char buf[PREFIX2STR_BUFFER]; +				prefix2str(&rpf.rpf_addr, buf, sizeof(buf)); +				zlog_debug( +					"%s: Skipping NHT update, addr %s is not in local cached DB.", +					__PRETTY_FUNCTION__, buf); +			} +			return 0; +		} +	} else { +		/* +		 * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE +		 */ +		return 0; +	} + +	pnc->last_update = pim_time_monotonic_usec(); +	distance = stream_getc(s); +	metric = stream_getl(s); +	nexthop_num = stream_getc(s); + +	if (nexthop_num) { +		pnc->nexthop_num = 0; // Only increment for pim enabled rpf. + +		for (i = 0; i < nexthop_num; i++) { +			nexthop = nexthop_new(); +			nexthop->type = stream_getc(s); +			switch (nexthop->type) { +			case NEXTHOP_TYPE_IPV4: +				nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); +				nexthop->ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IFINDEX: +				nexthop->ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IPV4_IFINDEX: +				nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); +				nexthop->ifindex = stream_getl(s); +				break; +			case NEXTHOP_TYPE_IPV6: +				stream_get(&nexthop->gate.ipv6, s, 16); +				break; +			case NEXTHOP_TYPE_IPV6_IFINDEX: +				stream_get(&nexthop->gate.ipv6, s, 16); +				nexthop->ifindex = stream_getl(s); +				ifp1 = if_lookup_by_index(nexthop->ifindex, +							  VRF_DEFAULT); +				nbr = pim_neighbor_find_if(ifp1); +				/* Overwrite with Nbr address as NH addr */ +				if (nbr) { +					nexthop->gate.ipv4 = nbr->source_addr; +					if (PIM_DEBUG_TRACE) { +						pim_inet4_dump("<nht_nbr?>", +							       nbr->source_addr, +							       str, +							       sizeof(str)); +						zlog_debug( +							"%s: NHT using pim nbr addr %s interface %s as rpf", +							__PRETTY_FUNCTION__, +							str, ifp1->name); +					} +				} else { +					if (PIM_DEBUG_TRACE) { +						pim_ifp = ifp1->info; +						zlog_debug( +							"%s: NHT pim nbr not found on interface %s nbr count:%d ", +							__PRETTY_FUNCTION__, +							ifp1->name, +							pim_ifp->pim_neighbor_list +								->count); +					} +					// Mark nexthop address to 0 until PIM +					// Nbr is resolved. +					nexthop->gate.ipv4.s_addr = +						PIM_NET_INADDR_ANY; +				} + +				break; +			default: +				/* do nothing */ +				break; +			} + +			if (PIM_DEBUG_TRACE) { +				char p_str[PREFIX2STR_BUFFER]; +				prefix2str(&p, p_str, sizeof(p_str)); +				zlog_debug( +					"%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", +					__PRETTY_FUNCTION__, p_str, i + 1, +					inet_ntoa(nexthop->gate.ipv4), +					nexthop->type, distance, metric); +			} + +			ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); +			if (!ifp) { +				if (PIM_DEBUG_ZEBRA) { +					char buf[NEXTHOP_STRLEN]; +					zlog_debug( +						"%s: could not find interface for ifindex %d (addr %s)", +						__PRETTY_FUNCTION__, +						nexthop->ifindex, +						nexthop2str(nexthop, buf, +							    sizeof(buf))); +				} +				nexthop_free(nexthop); +				continue; +			} + +			if (!ifp->info) { +				if (PIM_DEBUG_ZEBRA) { +					char buf[NEXTHOP_STRLEN]; +					zlog_debug( +						"%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", +						__PRETTY_FUNCTION__, ifp->name, +						nexthop->ifindex, +						nexthop2str(nexthop, buf, +							    sizeof(buf))); +				} +				nexthop_free(nexthop); +				continue; +			} + +			if (nhlist_tail) { +				nhlist_tail->next = nexthop; +				nhlist_tail = nexthop; +			} else { +				nhlist_tail = nexthop; +				nhlist_head = nexthop; +			} +			// Only keep track of nexthops which are PIM enabled. +			pnc->nexthop_num++; +		} +		/* Reset existing pnc->nexthop before assigning new list */ +		nexthops_free(pnc->nexthop); +		pnc->nexthop = nhlist_head; +		if (pnc->nexthop_num) { +			pnc->flags |= PIM_NEXTHOP_VALID; +			pnc->distance = distance; +			pnc->metric = metric; +		} +	} else { +		pnc->flags &= ~PIM_NEXTHOP_VALID; +		pnc->nexthop_num = nexthop_num; +		nexthops_free(pnc->nexthop); +		pnc->nexthop = NULL; +	} + +	if (PIM_DEBUG_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		prefix2str(&p, buf, sizeof(buf)); +		zlog_debug( +			"%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", +			__PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, +			vrf_id, listcount(pnc->upstream_list), +			listcount(pnc->rp_list)); +	} + +	pim_rpf_set_refresh_time(); + +	if (listcount(pnc->rp_list)) +		pim_update_rp_nh(pnc); +	if (listcount(pnc->upstream_list)) +		pim_update_upstream_nh(pnc); + +	return 0;  } -int -pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, -                         struct prefix *src, struct prefix *grp, -                         int neighbor_needed) +int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, +			    struct prefix *src, struct prefix *grp, +			    int neighbor_needed)  { -  struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; -  struct pim_neighbor *nbr = NULL; -  int num_ifindex; -  struct interface *ifp; -  int first_ifindex; -  int found = 0; -  uint8_t i = 0; -  uint32_t hash_val = 0, mod_val = 0; - -  if (PIM_DEBUG_TRACE) -    { -      char addr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -      zlog_debug ("%s: Looking up: %s, last lookup time: %lld", -                  __PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time); -    } - -  memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); -  num_ifindex = zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr, -                            PIM_NEXTHOP_LOOKUP_MAX); -  if (num_ifindex < 1) -    { -      char addr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -      zlog_warn ("%s %s: could not find nexthop ifindex for address %s", -                 __FILE__, __PRETTY_FUNCTION__, addr_str); -      return -1; -    } - -  //If PIM ECMP enable then choose ECMP path. -  if (qpim_ecmp_enable) -    { -      hash_val = pim_compute_ecmp_hash (src, grp); -      mod_val = hash_val % num_ifindex; -      if (PIM_DEBUG_PIM_TRACE_DETAIL) -        zlog_debug ("%s: hash_val %u mod_val %u", -                    __PRETTY_FUNCTION__, hash_val, mod_val); -    } - -  while (!found && (i < num_ifindex)) -    { -      first_ifindex = nexthop_tab[i].ifindex; - -      ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); -      if (!ifp) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -              zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", -                 __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); -            } -          if (i == mod_val) -            mod_val++; -          i++; -          continue; -        } - -      if (!ifp->info) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -              zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", -                 __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); -            } -          if (i == mod_val) -            mod_val++; -          i++; -          continue; -        } -      if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) -        { -          nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); -          if (PIM_DEBUG_PIM_TRACE_DETAIL) -            zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); -          if (!nbr && !if_is_loopback (ifp)) -            { -              if (i == mod_val) -                mod_val++; -              i++; -              if (PIM_DEBUG_ZEBRA) -                { -                  char addr_str[INET_ADDRSTRLEN]; -                  pim_inet4_dump ("<addr?>", addr, addr_str, -                                  sizeof (addr_str)); -                  zlog_debug ("%s: NBR not found on input interface %s (RPF for source %s)", -                     __PRETTY_FUNCTION__, ifp->name, addr_str); -                } -              continue; -            } -        } - -      if (i == mod_val) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char nexthop_str[PREFIX_STRLEN]; -              char addr_str[INET_ADDRSTRLEN]; -              pim_addr_dump ("<nexthop?>", &nexthop_tab[i].nexthop_addr, -                             nexthop_str, sizeof (nexthop_str)); -              pim_inet4_dump ("<addr?>", addr, addr_str, sizeof (addr_str)); -              zlog_debug ("%s %s: found nhop %s for addr %s interface %s metric %d dist %d", -                 __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str, -                 ifp->name, nexthop_tab[i].route_metric, -                 nexthop_tab[i].protocol_distance); -            } -          /* update nextop data */ -          nexthop->interface                = ifp; -          nexthop->mrib_nexthop_addr        = nexthop_tab[i].nexthop_addr; -          nexthop->mrib_metric_preference   = nexthop_tab[i].protocol_distance; -          nexthop->mrib_route_metric        = nexthop_tab[i].route_metric; -          nexthop->last_lookup              = addr; -          nexthop->last_lookup_time         = pim_time_monotonic_usec(); -          nexthop->nbr                      = nbr; -          found                             = 1; -        } -      i++; -    } -  if (found) -    return 0; -  else -    return -1; +	struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; +	struct pim_neighbor *nbr = NULL; +	int num_ifindex; +	struct interface *ifp; +	int first_ifindex; +	int found = 0; +	uint8_t i = 0; +	uint32_t hash_val = 0, mod_val = 0; + +	if (PIM_DEBUG_TRACE) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_debug("%s: Looking up: %s, last lookup time: %lld", +			   __PRETTY_FUNCTION__, addr_str, +			   nexthop->last_lookup_time); +	} + +	memset(nexthop_tab, 0, +	       sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); +	num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, +					     PIM_NEXTHOP_LOOKUP_MAX); +	if (num_ifindex < 1) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_warn( +			"%s %s: could not find nexthop ifindex for address %s", +			__FILE__, __PRETTY_FUNCTION__, addr_str); +		return -1; +	} + +	// If PIM ECMP enable then choose ECMP path. +	if (qpim_ecmp_enable) { +		hash_val = pim_compute_ecmp_hash(src, grp); +		mod_val = hash_val % num_ifindex; +		if (PIM_DEBUG_PIM_TRACE_DETAIL) +			zlog_debug("%s: hash_val %u mod_val %u", +				   __PRETTY_FUNCTION__, hash_val, mod_val); +	} + +	while (!found && (i < num_ifindex)) { +		first_ifindex = nexthop_tab[i].ifindex; + +		ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); +		if (!ifp) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s %s: could not find interface for ifindex %d (address %s)", +					__FILE__, __PRETTY_FUNCTION__, +					first_ifindex, addr_str); +			} +			if (i == mod_val) +				mod_val++; +			i++; +			continue; +		} + +		if (!ifp->info) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", +					__PRETTY_FUNCTION__, ifp->name, +					first_ifindex, addr_str); +			} +			if (i == mod_val) +				mod_val++; +			i++; +			continue; +		} +		if (neighbor_needed && !pim_if_connected_to_source(ifp, addr)) { +			nbr = pim_neighbor_find( +				ifp, nexthop_tab[i].nexthop_addr.u.prefix4); +			if (PIM_DEBUG_PIM_TRACE_DETAIL) +				zlog_debug("ifp name: %s, pim nbr: %p", +					   ifp->name, nbr); +			if (!nbr && !if_is_loopback(ifp)) { +				if (i == mod_val) +					mod_val++; +				i++; +				if (PIM_DEBUG_ZEBRA) { +					char addr_str[INET_ADDRSTRLEN]; +					pim_inet4_dump("<addr?>", addr, +						       addr_str, +						       sizeof(addr_str)); +					zlog_debug( +						"%s: NBR not found on input interface %s (RPF for source %s)", +						__PRETTY_FUNCTION__, ifp->name, +						addr_str); +				} +				continue; +			} +		} + +		if (i == mod_val) { +			if (PIM_DEBUG_ZEBRA) { +				char nexthop_str[PREFIX_STRLEN]; +				char addr_str[INET_ADDRSTRLEN]; +				pim_addr_dump("<nexthop?>", +					      &nexthop_tab[i].nexthop_addr, +					      nexthop_str, sizeof(nexthop_str)); +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s %s: found nhop %s for addr %s interface %s metric %d dist %d", +					__FILE__, __PRETTY_FUNCTION__, +					nexthop_str, addr_str, ifp->name, +					nexthop_tab[i].route_metric, +					nexthop_tab[i].protocol_distance); +			} +			/* update nextop data */ +			nexthop->interface = ifp; +			nexthop->mrib_nexthop_addr = +				nexthop_tab[i].nexthop_addr; +			nexthop->mrib_metric_preference = +				nexthop_tab[i].protocol_distance; +			nexthop->mrib_route_metric = +				nexthop_tab[i].route_metric; +			nexthop->last_lookup = addr; +			nexthop->last_lookup_time = pim_time_monotonic_usec(); +			nexthop->nbr = nbr; +			found = 1; +		} +		i++; +	} +	if (found) +		return 0; +	else +		return -1;  } -int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, -                                     struct prefix *src, struct prefix *grp) +int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src, +				     struct prefix *grp)  { -  struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; -  int num_ifindex; -  int vif_index; -  ifindex_t first_ifindex; -  uint32_t hash_val = 0, mod_val = 0; - -  memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); -  num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, -                                                PIM_NEXTHOP_LOOKUP_MAX); -  if (num_ifindex < 1) -    { -      if (PIM_DEBUG_ZEBRA) -        { -          char addr_str[INET_ADDRSTRLEN]; -          pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -          zlog_debug("%s %s: could not find nexthop ifindex for address %s", -                __FILE__, __PRETTY_FUNCTION__, -                addr_str); -        } -      return -1; -    } - -  //If PIM ECMP enable then choose ECMP path. -  if (qpim_ecmp_enable) -    { -      hash_val = pim_compute_ecmp_hash (src, grp); -      mod_val = hash_val % num_ifindex; -      if (PIM_DEBUG_PIM_TRACE_DETAIL) -        zlog_debug ("%s: hash_val %u mod_val %u", -                    __PRETTY_FUNCTION__, hash_val, mod_val); -    } - -  first_ifindex = nexthop_tab[mod_val].ifindex; - -  if (PIM_DEBUG_ZEBRA) -    { -      char addr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); -      zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s", -                __FILE__, __PRETTY_FUNCTION__, -                first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); -    } - -  vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); - -  if (vif_index < 0) -    { -      if (PIM_DEBUG_ZEBRA) -        { -          char addr_str[INET_ADDRSTRLEN]; -          pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -          zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s", -                  __FILE__, __PRETTY_FUNCTION__, -                     vif_index, addr_str); -        } -      return -2; -    } - -  return vif_index; +	struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; +	int num_ifindex; +	int vif_index; +	ifindex_t first_ifindex; +	uint32_t hash_val = 0, mod_val = 0; + +	memset(nexthop_tab, 0, +	       sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); +	num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, +					     PIM_NEXTHOP_LOOKUP_MAX); +	if (num_ifindex < 1) { +		if (PIM_DEBUG_ZEBRA) { +			char addr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			zlog_debug( +				"%s %s: could not find nexthop ifindex for address %s", +				__FILE__, __PRETTY_FUNCTION__, addr_str); +		} +		return -1; +	} + +	// If PIM ECMP enable then choose ECMP path. +	if (qpim_ecmp_enable) { +		hash_val = pim_compute_ecmp_hash(src, grp); +		mod_val = hash_val % num_ifindex; +		if (PIM_DEBUG_PIM_TRACE_DETAIL) +			zlog_debug("%s: hash_val %u mod_val %u", +				   __PRETTY_FUNCTION__, hash_val, mod_val); +	} + +	first_ifindex = nexthop_tab[mod_val].ifindex; + +	if (PIM_DEBUG_ZEBRA) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str)); +		zlog_debug( +			"%s %s: found nexthop ifindex=%d (interface %s) for address %s", +			__FILE__, __PRETTY_FUNCTION__, first_ifindex, +			ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); +	} + +	vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); + +	if (vif_index < 0) { +		if (PIM_DEBUG_ZEBRA) { +			char addr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			zlog_debug( +				"%s %s: low vif_index=%d < 1 nexthop for address %s", +				__FILE__, __PRETTY_FUNCTION__, vif_index, +				addr_str); +		} +		return -2; +	} + +	return vif_index;  } diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h index 6bd2249928..fb8d836235 100644 --- a/pimd/pim_nht.h +++ b/pimd/pim_nht.h @@ -30,42 +30,42 @@  #include "pim_rpf.h"  /* PIM nexthop cache value structure. */ -struct pim_nexthop_cache -{ -  struct pim_rpf rpf; -  /* IGP route's metric. */ -  u_int32_t metric; -  uint32_t  distance; -  /* Nexthop number and nexthop linked list. */ -  u_char nexthop_num; -  struct nexthop *nexthop; -  int64_t last_update; -  u_int16_t flags; +struct pim_nexthop_cache { +	struct pim_rpf rpf; +	/* IGP route's metric. */ +	u_int32_t metric; +	uint32_t distance; +	/* Nexthop number and nexthop linked list. */ +	u_char nexthop_num; +	struct nexthop *nexthop; +	int64_t last_update; +	u_int16_t flags;  #define PIM_NEXTHOP_VALID             (1 << 0) -  struct list *rp_list; -  struct list *upstream_list; +	struct list *rp_list; +	struct list *upstream_list;  }; -int pim_parse_nexthop_update (int command, struct zclient *zclient, -                              zebra_size_t length, vrf_id_t vrf_id); -int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, -                               struct rp_info *rp, struct pim_nexthop_cache *out_pnc); -void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, -                                 struct rp_info *rp); -struct pim_nexthop_cache *pim_nexthop_cache_add (struct pim_rpf *rpf_addr); -struct pim_nexthop_cache *pim_nexthop_cache_find (struct pim_rpf *rpf); -uint32_t pim_compute_ecmp_hash (struct prefix *src, struct prefix *grp); -int pim_ecmp_nexthop_search (struct pim_nexthop_cache * pnc, -                         struct pim_nexthop *nexthop, struct prefix *src, -                         struct prefix *grp, int neighbor_needed); -int pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, -                         struct prefix *src, struct prefix *grp, -                         int neighbor_needed); -void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, -                          int command); -int pim_update_rp_nh (struct pim_nexthop_cache *pnc); -void pim_resolve_upstream_nh (struct prefix *nht_p); -int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, -                          struct prefix *src, struct prefix *grp); +int pim_parse_nexthop_update(int command, struct zclient *zclient, +			     zebra_size_t length, vrf_id_t vrf_id); +int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up, +			      struct rp_info *rp, +			      struct pim_nexthop_cache *out_pnc); +void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up, +				struct rp_info *rp); +struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr); +struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf); +uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp); +int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc, +			    struct pim_nexthop *nexthop, struct prefix *src, +			    struct prefix *grp, int neighbor_needed); +int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, +			    struct prefix *src, struct prefix *grp, +			    int neighbor_needed); +void pim_sendmsg_zebra_rnh(struct zclient *zclient, +			   struct pim_nexthop_cache *pnc, int command); +int pim_update_rp_nh(struct pim_nexthop_cache *pnc); +void pim_resolve_upstream_nh(struct prefix *nht_p); +int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src, +				     struct prefix *grp);  #endif diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 66be2be6f5..aeef0ff4ec 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -35,435 +35,477 @@  struct list *pim_channel_oil_list = NULL;  struct hash *pim_channel_oil_hash = NULL; -char * -pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size) +char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)  { -  struct prefix_sg sg; -  int i; - -  memset (buf, 0, size); -  sg.src = c_oil->oil.mfcc_origin; -  sg.grp = c_oil->oil.mfcc_mcastgrp; -  sprintf(buf, "%s IIF: %d, OIFS: ", -          pim_str_sg_dump (&sg), c_oil->oil.mfcc_parent); - -  for (i = 0 ; i < MAXVIFS ; i++) -    { -      if (c_oil->oil.mfcc_ttls[i] != 0) -        { -          char buf1[10]; -          sprintf(buf1, "%d ", i); -          strcat(buf, buf1); -        } -    } - -  return buf; +	struct prefix_sg sg; +	int i; + +	memset(buf, 0, size); +	sg.src = c_oil->oil.mfcc_origin; +	sg.grp = c_oil->oil.mfcc_mcastgrp; +	sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg), +		c_oil->oil.mfcc_parent); + +	for (i = 0; i < MAXVIFS; i++) { +		if (c_oil->oil.mfcc_ttls[i] != 0) { +			char buf1[10]; +			sprintf(buf1, "%d ", i); +			strcat(buf, buf1); +		} +	} + +	return buf;  } -static int -pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) +static int pim_channel_oil_compare(struct channel_oil *c1, +				   struct channel_oil *c2)  { -  if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) -     return -1; +	if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) +	    < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) +		return -1; -   if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) -     return 1; +	if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) +	    > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) +		return 1; -   if (ntohl(c1->oil.mfcc_origin.s_addr) < ntohl(c2->oil.mfcc_origin.s_addr)) -     return -1; +	if (ntohl(c1->oil.mfcc_origin.s_addr) +	    < ntohl(c2->oil.mfcc_origin.s_addr)) +		return -1; -   if (ntohl(c1->oil.mfcc_origin.s_addr) > ntohl(c2->oil.mfcc_origin.s_addr)) -     return 1; +	if (ntohl(c1->oil.mfcc_origin.s_addr) +	    > ntohl(c2->oil.mfcc_origin.s_addr)) +		return 1; -   return 0; +	return 0;  } -static int -pim_oil_equal (const void *arg1, const void *arg2) +static int pim_oil_equal(const void *arg1, const void *arg2)  { -  const struct channel_oil *c1 = (const struct channel_oil *)arg1; -  const struct channel_oil *c2 = (const struct channel_oil *)arg2; +	const struct channel_oil *c1 = (const struct channel_oil *)arg1; +	const struct channel_oil *c2 = (const struct channel_oil *)arg2; -  if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) && -      (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) -    return 1; +	if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) +	    && (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) +		return 1; -  return 0; +	return 0;  } -static unsigned int -pim_oil_hash_key (void *arg) +static unsigned int pim_oil_hash_key(void *arg)  { -  struct channel_oil *oil = (struct channel_oil *)arg; +	struct channel_oil *oil = (struct channel_oil *)arg; -  return jhash_2words (oil->oil.mfcc_mcastgrp.s_addr, oil->oil.mfcc_origin.s_addr, 0); +	return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr, +			    oil->oil.mfcc_origin.s_addr, 0);  } -void -pim_oil_init (void) +void pim_oil_init(void)  { -  pim_channel_oil_hash = hash_create_size (8192, pim_oil_hash_key, -					   pim_oil_equal, NULL); - -  pim_channel_oil_list = list_new(); -  if (!pim_channel_oil_list) { -    zlog_err("%s %s: failure: channel_oil_list=list_new()", -	     __FILE__, __PRETTY_FUNCTION__); -    return; -  } -  pim_channel_oil_list->del = (void (*)(void *)) pim_channel_oil_free; -  pim_channel_oil_list->cmp = (int (*)(void *, void *)) pim_channel_oil_compare; +	pim_channel_oil_hash = +		hash_create_size(8192, pim_oil_hash_key, pim_oil_equal, NULL); + +	pim_channel_oil_list = list_new(); +	if (!pim_channel_oil_list) { +		zlog_err("%s %s: failure: channel_oil_list=list_new()", +			 __FILE__, __PRETTY_FUNCTION__); +		return; +	} +	pim_channel_oil_list->del = (void (*)(void *))pim_channel_oil_free; +	pim_channel_oil_list->cmp = +		(int (*)(void *, void *))pim_channel_oil_compare;  } -void -pim_oil_terminate (void) +void pim_oil_terminate(void)  { -  if (pim_channel_oil_list) -    list_free(pim_channel_oil_list); -  pim_channel_oil_list = NULL; +	if (pim_channel_oil_list) +		list_free(pim_channel_oil_list); +	pim_channel_oil_list = NULL; -  if (pim_channel_oil_hash) -    hash_free (pim_channel_oil_hash); -  pim_channel_oil_hash = NULL; +	if (pim_channel_oil_hash) +		hash_free(pim_channel_oil_hash); +	pim_channel_oil_hash = NULL;  }  void pim_channel_oil_free(struct channel_oil *c_oil)  { -  XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); +	XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil);  } -static struct channel_oil * -pim_find_channel_oil(struct prefix_sg *sg) +static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg)  { -  struct channel_oil *c_oil = NULL; -  struct channel_oil lookup; +	struct channel_oil *c_oil = NULL; +	struct channel_oil lookup; -  lookup.oil.mfcc_mcastgrp = sg->grp; -  lookup.oil.mfcc_origin   = sg->src; +	lookup.oil.mfcc_mcastgrp = sg->grp; +	lookup.oil.mfcc_origin = sg->src; -  c_oil = hash_lookup (pim_channel_oil_hash, &lookup); +	c_oil = hash_lookup(pim_channel_oil_hash, &lookup); -  return c_oil; +	return c_oil;  }  struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,  					int input_vif_index)  { -  struct channel_oil *c_oil; -  struct interface *ifp; - -  c_oil = pim_find_channel_oil(sg); -  if (c_oil) { -    if (c_oil->oil.mfcc_parent != input_vif_index) -      { -        c_oil->oil_inherited_rescan = 1; -        if (PIM_DEBUG_MROUTE) -          zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d", -                      __PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index); -      } -    c_oil->oil.mfcc_parent = input_vif_index; -    ++c_oil->oil_ref_count; -    c_oil->up = pim_upstream_find(sg); //channel might be present prior to upstream -    return c_oil; -  } - -  ifp = pim_if_find_by_vif_index(input_vif_index); -  if (!ifp) { -    /* warning only */ -    zlog_warn("%s: (S,G)=%s could not find input interface for input_vif_index=%d", -	      __PRETTY_FUNCTION__, -	      pim_str_sg_dump (sg), input_vif_index); -  } - -  c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); -  if (!c_oil) { -    zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); -    return NULL; -  } - -  c_oil->oil.mfcc_mcastgrp = sg->grp; -  c_oil->oil.mfcc_origin   = sg->src; -  c_oil = hash_get (pim_channel_oil_hash, c_oil, hash_alloc_intern); - -  c_oil->oil.mfcc_parent   = input_vif_index; -  c_oil->oil_ref_count     = 1; -  c_oil->installed         = 0; -  c_oil->up = pim_upstream_find(sg); - -  listnode_add_sort(pim_channel_oil_list, c_oil); - -  return c_oil; +	struct channel_oil *c_oil; +	struct interface *ifp; + +	c_oil = pim_find_channel_oil(sg); +	if (c_oil) { +		if (c_oil->oil.mfcc_parent != input_vif_index) { +			c_oil->oil_inherited_rescan = 1; +			if (PIM_DEBUG_MROUTE) +				zlog_debug( +					"%s: Existing channel oil %s points to %d, modifying to point at %d", +					__PRETTY_FUNCTION__, +					pim_str_sg_dump(sg), +					c_oil->oil.mfcc_parent, +					input_vif_index); +		} +		c_oil->oil.mfcc_parent = input_vif_index; +		++c_oil->oil_ref_count; +		c_oil->up = pim_upstream_find( +			sg); // channel might be present prior to upstream +		return c_oil; +	} + +	ifp = pim_if_find_by_vif_index(input_vif_index); +	if (!ifp) { +		/* warning only */ +		zlog_warn( +			"%s: (S,G)=%s could not find input interface for input_vif_index=%d", +			__PRETTY_FUNCTION__, pim_str_sg_dump(sg), +			input_vif_index); +	} + +	c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); +	if (!c_oil) { +		zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); +		return NULL; +	} + +	c_oil->oil.mfcc_mcastgrp = sg->grp; +	c_oil->oil.mfcc_origin = sg->src; +	c_oil = hash_get(pim_channel_oil_hash, c_oil, hash_alloc_intern); + +	c_oil->oil.mfcc_parent = input_vif_index; +	c_oil->oil_ref_count = 1; +	c_oil->installed = 0; +	c_oil->up = pim_upstream_find(sg); + +	listnode_add_sort(pim_channel_oil_list, c_oil); + +	return c_oil;  }  void pim_channel_oil_del(struct channel_oil *c_oil)  { -  --c_oil->oil_ref_count; - -  if (c_oil->oil_ref_count < 1) { -    /* -     * notice that listnode_delete() can't be moved -     * into pim_channel_oil_free() because the later is -     * called by list_delete_all_node() -     */ -    c_oil->up = NULL; -    listnode_delete(pim_channel_oil_list, c_oil); -    hash_release (pim_channel_oil_hash, c_oil); - -    pim_channel_oil_free(c_oil); -  } +	--c_oil->oil_ref_count; + +	if (c_oil->oil_ref_count < 1) { +		/* +		 * notice that listnode_delete() can't be moved +		 * into pim_channel_oil_free() because the later is +		 * called by list_delete_all_node() +		 */ +		c_oil->up = NULL; +		listnode_delete(pim_channel_oil_list, c_oil); +		hash_release(pim_channel_oil_hash, c_oil); + +		pim_channel_oil_free(c_oil); +	}  } -int -pim_channel_del_oif (struct channel_oil *channel_oil, -		     struct interface *oif, -		     uint32_t proto_mask) +int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif, +			uint32_t proto_mask)  { -  struct pim_interface *pim_ifp; - -  zassert (channel_oil); -  zassert (oif); - -  pim_ifp = oif->info; - -  /* -   * Don't do anything if we've been asked to remove a source -   * that is not actually on it. -   */ -  if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) -    { -      if (PIM_DEBUG_MROUTE) -	{ -	  char group_str[INET_ADDRSTRLEN]; -	  char source_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	  pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	  zlog_debug("%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", -		     __FILE__, __PRETTY_FUNCTION__, -		     proto_mask, channel_oil->oif_flags[pim_ifp->mroute_vif_index], -		     oif->name, pim_ifp->mroute_vif_index, -		     channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], -		     source_str, group_str); +	struct pim_interface *pim_ifp; + +	zassert(channel_oil); +	zassert(oif); + +	pim_ifp = oif->info; + +	/* +	 * Don't do anything if we've been asked to remove a source +	 * that is not actually on it. +	 */ +	if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) { +		if (PIM_DEBUG_MROUTE) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", +				       channel_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			pim_inet4_dump("<source?>", +				       channel_oil->oil.mfcc_origin, source_str, +				       sizeof(source_str)); +			zlog_debug( +				"%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, proto_mask, +				channel_oil +					->oif_flags[pim_ifp->mroute_vif_index], +				oif->name, pim_ifp->mroute_vif_index, +				channel_oil->oil +					.mfcc_ttls[pim_ifp->mroute_vif_index], +				source_str, group_str); +		} +		return 0; +	} + +	channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; + +	if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) { +		if (PIM_DEBUG_MROUTE) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", +				       channel_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			pim_inet4_dump("<source?>", +				       channel_oil->oil.mfcc_origin, source_str, +				       sizeof(source_str)); +			zlog_debug( +				"%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, oif->name, +				pim_ifp->mroute_vif_index, +				channel_oil->oil +					.mfcc_ttls[pim_ifp->mroute_vif_index], +				source_str, group_str); +		} +		return 0; +	} + +	channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; + +	if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { +		if (PIM_DEBUG_MROUTE) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", +				       channel_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			pim_inet4_dump("<source?>", +				       channel_oil->oil.mfcc_origin, source_str, +				       sizeof(source_str)); +			zlog_debug( +				"%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, oif->name, +				pim_ifp->mroute_vif_index, source_str, +				group_str); +		} +		return -1;  	} -      return 0; -    } - -  channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; - -  if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) -    { -      if (PIM_DEBUG_MROUTE) -	{ -	  char group_str[INET_ADDRSTRLEN]; -	  char source_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	  pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	  zlog_debug("%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", -		     __FILE__, __PRETTY_FUNCTION__, -		     oif->name, pim_ifp->mroute_vif_index, -		     channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], -		     source_str, group_str); + +	--channel_oil->oil_size; + +	if (PIM_DEBUG_MROUTE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, +			       group_str, sizeof(group_str)); +		pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, +			       source_str, sizeof(source_str)); +		zlog_debug( +			"%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d", +			__FILE__, __PRETTY_FUNCTION__, source_str, group_str, +			proto_mask, channel_oil->oil.mfcc_parent, oif->name, +			pim_ifp->mroute_vif_index);  	} -      return 0; -    } - -  channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; - -  if (pim_mroute_add (channel_oil, __PRETTY_FUNCTION__)) { -    if (PIM_DEBUG_MROUTE) -      { -        char group_str[INET_ADDRSTRLEN]; -        char source_str[INET_ADDRSTRLEN]; -        pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -        pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -        zlog_debug("%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", -                   __FILE__, __PRETTY_FUNCTION__, -                   oif->name, pim_ifp->mroute_vif_index, -                   source_str, group_str); -      } -    return -1; -  } - -  --channel_oil->oil_size; - -  if (PIM_DEBUG_MROUTE) -    { -      char group_str[INET_ADDRSTRLEN]; -      char source_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -      pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -      zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d", -		 __FILE__, __PRETTY_FUNCTION__, -		 source_str, group_str, -	         proto_mask, channel_oil->oil.mfcc_parent ,oif->name, pim_ifp->mroute_vif_index); -    } - -  return 0; + +	return 0;  } -int pim_channel_add_oif(struct channel_oil *channel_oil, -		   struct interface *oif, -		   uint32_t proto_mask) +int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif, +			uint32_t proto_mask)  { -  struct pim_interface *pim_ifp; -  int old_ttl; - -  /* -   * If we've gotten here we've gone bad, but let's -   * not take down pim -   */ -  if (!channel_oil) -    { -      zlog_warn ("Attempt to Add OIF for non-existent channel oil"); -      return -1; -    } +	struct pim_interface *pim_ifp; +	int old_ttl; + +	/* +	 * If we've gotten here we've gone bad, but let's +	 * not take down pim +	 */ +	if (!channel_oil) { +		zlog_warn("Attempt to Add OIF for non-existent channel oil"); +		return -1; +	} -  pim_ifp = oif->info; +	pim_ifp = oif->info;  #ifdef PIM_ENFORCE_LOOPFREE_MFC -  /* -    Prevent creating MFC entry with OIF=IIF. - -    This is a protection against implementation mistakes. - -    PIM protocol implicitely ensures loopfree multicast topology. - -    IGMP must be protected against adding looped MFC entries created -    by both source and receiver attached to the same interface. See -    TODO T22. -  */ -  if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { -    channel_oil->oil_inherited_rescan = 1; -    if (PIM_DEBUG_MROUTE) -      { -	char group_str[INET_ADDRSTRLEN]; -	char source_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	zlog_debug("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", -		   __FILE__, __PRETTY_FUNCTION__, -		   proto_mask, oif->name, pim_ifp->mroute_vif_index, -		   source_str, group_str); -      } -    return -2; -  } +	/* +	  Prevent creating MFC entry with OIF=IIF. + +	  This is a protection against implementation mistakes. + +	  PIM protocol implicitely ensures loopfree multicast topology. + +	  IGMP must be protected against adding looped MFC entries created +	  by both source and receiver attached to the same interface. See +	  TODO T22. +	*/ +	if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { +		channel_oil->oil_inherited_rescan = 1; +		if (PIM_DEBUG_MROUTE) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", +				       channel_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			pim_inet4_dump("<source?>", +				       channel_oil->oil.mfcc_origin, source_str, +				       sizeof(source_str)); +			zlog_debug( +				"%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, proto_mask, +				oif->name, pim_ifp->mroute_vif_index, +				source_str, group_str); +		} +		return -2; +	}  #endif -  /* Prevent single protocol from subscribing same interface to -     channel (S,G) multiple times */ -  if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) { -    if (PIM_DEBUG_MROUTE) -      { -	char group_str[INET_ADDRSTRLEN]; -	char source_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	zlog_debug("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", -		   __FILE__, __PRETTY_FUNCTION__, -		   proto_mask, oif->name, pim_ifp->mroute_vif_index, -		   channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], -		   source_str, group_str); -      } -    return -3; -  } - -  /* Allow other protocol to request subscription of same interface to -   * channel (S,G), we need to note this information -   */ -  if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) { - -    channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec(); -    channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; -    /* Check the OIF really exists before returning, and only log -       warning otherwise */ -    if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { -      { -        char group_str[INET_ADDRSTRLEN]; -        char source_str[INET_ADDRSTRLEN]; -        pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -        pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -        zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", -                  __FILE__, __PRETTY_FUNCTION__, -                  proto_mask, oif->name, pim_ifp->mroute_vif_index, -                  channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], -                  source_str, group_str); -      } -    } - -    return 0; -  } - -  old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; - -  if (old_ttl > 0) { -    if (PIM_DEBUG_MROUTE) -      { -	char group_str[INET_ADDRSTRLEN]; -	char source_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	zlog_debug("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)", -		   __FILE__, __PRETTY_FUNCTION__, -		   oif->name, pim_ifp->mroute_vif_index, -		   source_str, group_str); -      } -    return -4; -  } - -  channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL; - -  if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { -    if (PIM_DEBUG_MROUTE) -      { -	char group_str[INET_ADDRSTRLEN]; -	char source_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	zlog_debug("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", -		   __FILE__, __PRETTY_FUNCTION__, -		   oif->name, pim_ifp->mroute_vif_index, -		   source_str, group_str); -      } - -    channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl; -    return -5; -  } - -  channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec(); -  ++channel_oil->oil_size; -  channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; - -  if (PIM_DEBUG_MROUTE) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -    pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -    zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", -	       __FILE__, __PRETTY_FUNCTION__, -	       source_str, group_str, -	       proto_mask, oif->name, pim_ifp->mroute_vif_index); -  } - -  return 0; +	/* Prevent single protocol from subscribing same interface to +	   channel (S,G) multiple times */ +	if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) { +		if (PIM_DEBUG_MROUTE) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", +				       channel_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			pim_inet4_dump("<source?>", +				       channel_oil->oil.mfcc_origin, source_str, +				       sizeof(source_str)); +			zlog_debug( +				"%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, proto_mask, +				oif->name, pim_ifp->mroute_vif_index, +				channel_oil->oil +					.mfcc_ttls[pim_ifp->mroute_vif_index], +				source_str, group_str); +		} +		return -3; +	} + +	/* Allow other protocol to request subscription of same interface to +	 * channel (S,G), we need to note this information +	 */ +	if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] +	    & PIM_OIF_FLAG_PROTO_ANY) { + +		channel_oil->oif_creation[pim_ifp->mroute_vif_index] = +			pim_time_monotonic_sec(); +		channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; +		/* Check the OIF really exists before returning, and only log +		   warning otherwise */ +		if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { +			{ +				char group_str[INET_ADDRSTRLEN]; +				char source_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<group?>", +					       channel_oil->oil.mfcc_mcastgrp, +					       group_str, sizeof(group_str)); +				pim_inet4_dump("<source?>", +					       channel_oil->oil.mfcc_origin, +					       source_str, sizeof(source_str)); +				zlog_warn( +					"%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", +					__FILE__, __PRETTY_FUNCTION__, +					proto_mask, oif->name, +					pim_ifp->mroute_vif_index, +					channel_oil->oil.mfcc_ttls +						[pim_ifp->mroute_vif_index], +					source_str, group_str); +			} +		} + +		return 0; +	} + +	old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; + +	if (old_ttl > 0) { +		if (PIM_DEBUG_MROUTE) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", +				       channel_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			pim_inet4_dump("<source?>", +				       channel_oil->oil.mfcc_origin, source_str, +				       sizeof(source_str)); +			zlog_debug( +				"%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, oif->name, +				pim_ifp->mroute_vif_index, source_str, +				group_str); +		} +		return -4; +	} + +	channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = +		PIM_MROUTE_MIN_TTL; + +	if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { +		if (PIM_DEBUG_MROUTE) { +			char group_str[INET_ADDRSTRLEN]; +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<group?>", +				       channel_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			pim_inet4_dump("<source?>", +				       channel_oil->oil.mfcc_origin, source_str, +				       sizeof(source_str)); +			zlog_debug( +				"%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, oif->name, +				pim_ifp->mroute_vif_index, source_str, +				group_str); +		} + +		channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl; +		return -5; +	} + +	channel_oil->oif_creation[pim_ifp->mroute_vif_index] = +		pim_time_monotonic_sec(); +	++channel_oil->oil_size; +	channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; + +	if (PIM_DEBUG_MROUTE) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, +			       group_str, sizeof(group_str)); +		pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, +			       source_str, sizeof(source_str)); +		zlog_debug( +			"%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", +			__FILE__, __PRETTY_FUNCTION__, source_str, group_str, +			proto_mask, oif->name, pim_ifp->mroute_vif_index); +	} + +	return 0;  } -int -pim_channel_oil_empty (struct channel_oil *c_oil) +int pim_channel_oil_empty(struct channel_oil *c_oil)  { -  static uint32_t zero[MAXVIFS]; -  static int inited = 0; - -  if (!c_oil) -    return 1; -  /* -   * Not sure that this is necessary, but I would rather ensure -   * that this works. -   */ -  if (!inited) -    { -      memset(&zero, 0, sizeof(uint32_t) * MAXVIFS); -      inited = 1; -    } - -  return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t)); +	static uint32_t zero[MAXVIFS]; +	static int inited = 0; + +	if (!c_oil) +		return 1; +	/* +	 * Not sure that this is necessary, but I would rather ensure +	 * that this works. +	 */ +	if (!inited) { +		memset(&zero, 0, sizeof(uint32_t) * MAXVIFS); +		inited = 1; +	} + +	return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t));  } diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 02c7e740ef..f537062c7a 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -34,10 +34,9 @@  #define PIM_OIF_FLAG_PROTO_PIM    (1 << 1)  #define PIM_OIF_FLAG_PROTO_SOURCE (1 << 2)  #define PIM_OIF_FLAG_PROTO_STAR   (1 << 3) -#define PIM_OIF_FLAG_PROTO_ANY    (PIM_OIF_FLAG_PROTO_IGMP | \ -                                   PIM_OIF_FLAG_PROTO_PIM | \ -                                   PIM_OIF_FLAG_PROTO_SOURCE | \ -                                   PIM_OIF_FLAG_PROTO_STAR) +#define PIM_OIF_FLAG_PROTO_ANY                                                 \ +	(PIM_OIF_FLAG_PROTO_IGMP | PIM_OIF_FLAG_PROTO_PIM                      \ +	 | PIM_OIF_FLAG_PROTO_SOURCE | PIM_OIF_FLAG_PROTO_STAR)  /*   * We need a pimreg vif id from the kernel. @@ -50,16 +49,14 @@  #define PIM_OIF_PIM_REGISTER_VIF   0  #define PIM_MAX_USABLE_VIFS        (MAXVIFS - 1) - -struct channel_counts -{ -  unsigned long long lastused; -  unsigned long pktcnt; -  unsigned long oldpktcnt; -  unsigned long bytecnt; -  unsigned long oldbytecnt; -  unsigned long wrong_if; -  unsigned long oldwrong_if; +struct channel_counts { +	unsigned long long lastused; +	unsigned long pktcnt; +	unsigned long oldpktcnt; +	unsigned long bytecnt; +	unsigned long oldbytecnt; +	unsigned long wrong_if; +	unsigned long oldwrong_if;  };  /* @@ -70,35 +67,33 @@ struct channel_counts  */  struct channel_oil { -  struct mfcctl oil; -  int           installed; -  int           oil_inherited_rescan; -  int           oil_size; -  int           oil_ref_count; -  time_t        oif_creation[MAXVIFS]; -  uint32_t      oif_flags[MAXVIFS]; -  struct channel_counts cc; -  struct pim_upstream *up; +	struct mfcctl oil; +	int installed; +	int oil_inherited_rescan; +	int oil_size; +	int oil_ref_count; +	time_t oif_creation[MAXVIFS]; +	uint32_t oif_flags[MAXVIFS]; +	struct channel_counts cc; +	struct pim_upstream *up;  };  extern struct list *pim_channel_oil_list; -void pim_oil_init (void); -void pim_oil_terminate (void); +void pim_oil_init(void); +void pim_oil_terminate(void);  void pim_channel_oil_free(struct channel_oil *c_oil);  struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg,  					int input_vif_index);  void pim_channel_oil_del(struct channel_oil *c_oil); -int pim_channel_add_oif(struct channel_oil *c_oil, -			struct interface *oif, +int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif, +			uint32_t proto_mask); +int pim_channel_del_oif(struct channel_oil *c_oil, struct interface *oif,  			uint32_t proto_mask); -int pim_channel_del_oif (struct channel_oil *c_oil, -			 struct interface *oif, -			 uint32_t proto_mask); -int pim_channel_oil_empty (struct channel_oil *c_oil); +int pim_channel_oil_empty(struct channel_oil *c_oil); -char *pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size); +char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size);  #endif /* PIM_OIL_H */ diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f6a5bb1226..21892f3477 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -40,670 +40,673 @@  #include "pim_register.h"  static int on_pim_hello_send(struct thread *t); -static int pim_hello_send(struct interface *ifp, -			  uint16_t holdtime); +static int pim_hello_send(struct interface *ifp, uint16_t holdtime); -static -const char *pim_pim_msgtype2str (enum pim_msg_type type) +static const char *pim_pim_msgtype2str(enum pim_msg_type type)  { -  switch (type) -    { -    case PIM_MSG_TYPE_HELLO:      return "HELLO"; -    case PIM_MSG_TYPE_REGISTER:   return "REGISTER"; -    case PIM_MSG_TYPE_REG_STOP:   return "REGSTOP"; -    case PIM_MSG_TYPE_JOIN_PRUNE: return "JOINPRUNE"; -    case PIM_MSG_TYPE_BOOTSTRAP:  return "BOOT"; -    case PIM_MSG_TYPE_ASSERT:     return "ASSERT"; -    case PIM_MSG_TYPE_GRAFT:      return "GRAFT"; -    case PIM_MSG_TYPE_GRAFT_ACK:  return "GACK"; -    case PIM_MSG_TYPE_CANDIDATE:  return "CANDIDATE"; -    } - -  return "UNKNOWN"; +	switch (type) { +	case PIM_MSG_TYPE_HELLO: +		return "HELLO"; +	case PIM_MSG_TYPE_REGISTER: +		return "REGISTER"; +	case PIM_MSG_TYPE_REG_STOP: +		return "REGSTOP"; +	case PIM_MSG_TYPE_JOIN_PRUNE: +		return "JOINPRUNE"; +	case PIM_MSG_TYPE_BOOTSTRAP: +		return "BOOT"; +	case PIM_MSG_TYPE_ASSERT: +		return "ASSERT"; +	case PIM_MSG_TYPE_GRAFT: +		return "GRAFT"; +	case PIM_MSG_TYPE_GRAFT_ACK: +		return "GACK"; +	case PIM_MSG_TYPE_CANDIDATE: +		return "CANDIDATE"; +	} + +	return "UNKNOWN";  }  static void sock_close(struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; - -  if (PIM_DEBUG_PIM_TRACE) { -    if (pim_ifp->t_pim_sock_read) { -      zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s", -		 pim_ifp->pim_sock_fd, -		 ifp->name); -    } -  } -  THREAD_OFF(pim_ifp->t_pim_sock_read); - -  if (PIM_DEBUG_PIM_TRACE) { -    if (pim_ifp->t_pim_hello_timer) { -      zlog_debug("Cancelling PIM hello timer for interface %s", -		 ifp->name); -    } -  } -  THREAD_OFF(pim_ifp->t_pim_hello_timer); - -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("Deleting PIM socket fd=%d on interface %s", -	       pim_ifp->pim_sock_fd, ifp->name); -  } - -  /* -   * If the fd is already deleted no need to do anything here -   */ -  if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) { -    zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s", -	      pim_ifp->pim_sock_fd, ifp->name, -	      errno, safe_strerror(errno)); -  } -   -  pim_ifp->pim_sock_fd = -1; -  pim_ifp->pim_sock_creation = 0; +	struct pim_interface *pim_ifp = ifp->info; + +	if (PIM_DEBUG_PIM_TRACE) { +		if (pim_ifp->t_pim_sock_read) { +			zlog_debug( +				"Cancelling READ event for PIM socket fd=%d on interface %s", +				pim_ifp->pim_sock_fd, ifp->name); +		} +	} +	THREAD_OFF(pim_ifp->t_pim_sock_read); + +	if (PIM_DEBUG_PIM_TRACE) { +		if (pim_ifp->t_pim_hello_timer) { +			zlog_debug( +				"Cancelling PIM hello timer for interface %s", +				ifp->name); +		} +	} +	THREAD_OFF(pim_ifp->t_pim_hello_timer); + +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("Deleting PIM socket fd=%d on interface %s", +			   pim_ifp->pim_sock_fd, ifp->name); +	} + +	/* +	 * If the fd is already deleted no need to do anything here +	 */ +	if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) { +		zlog_warn( +			"Failure closing PIM socket fd=%d on interface %s: errno=%d: %s", +			pim_ifp->pim_sock_fd, ifp->name, errno, +			safe_strerror(errno)); +	} + +	pim_ifp->pim_sock_fd = -1; +	pim_ifp->pim_sock_creation = 0;  }  void pim_sock_delete(struct interface *ifp, const char *delete_message)  { -  zlog_info("PIM INTERFACE DOWN: on interface %s: %s", -	    ifp->name, delete_message); - -  if (!ifp->info) { -    zlog_err("%s: %s: but PIM not enabled on interface %s (!)", -	     __PRETTY_FUNCTION__, delete_message, ifp->name); -    return; -  } - -  /* -    RFC 4601: 4.3.1.  Sending Hello Messages -     -    Before an interface goes down or changes primary IP address, a Hello -    message with a zero HoldTime should be sent immediately (with the -    old IP address if the IP address changed). -  */ -  pim_hello_send(ifp, 0 /* zero-sec holdtime */); - -  pim_neighbor_delete_all(ifp, delete_message); - -  sock_close(ifp); +	zlog_info("PIM INTERFACE DOWN: on interface %s: %s", ifp->name, +		  delete_message); + +	if (!ifp->info) { +		zlog_err("%s: %s: but PIM not enabled on interface %s (!)", +			 __PRETTY_FUNCTION__, delete_message, ifp->name); +		return; +	} + +	/* +	  RFC 4601: 4.3.1.  Sending Hello Messages + +	  Before an interface goes down or changes primary IP address, a Hello +	  message with a zero HoldTime should be sent immediately (with the +	  old IP address if the IP address changed). +	*/ +	pim_hello_send(ifp, 0 /* zero-sec holdtime */); + +	pim_neighbor_delete_all(ifp, delete_message); + +	sock_close(ifp);  }  int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)  { -  struct ip *ip_hdr; -  size_t ip_hlen; /* ip header length in bytes */ -  char src_str[INET_ADDRSTRLEN]; -  char dst_str[INET_ADDRSTRLEN]; -  uint8_t *pim_msg; -  int pim_msg_len; -  uint16_t pim_checksum; /* received checksum */ -  uint16_t checksum;     /* computed checksum */ -  struct pim_neighbor *neigh; -  struct pim_msg_header *header; - -  if (len < sizeof(*ip_hdr)) { -    if (PIM_DEBUG_PIM_PACKETS) -      zlog_debug("PIM packet size=%zu shorter than minimum=%zu", -		 len, sizeof(*ip_hdr)); -    return -1; -  } - -  ip_hdr = (struct ip *) buf; -  ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - -  pim_msg = buf + ip_hlen; -  pim_msg_len = len - ip_hlen; - -  header = (struct pim_msg_header *)pim_msg; -  if (pim_msg_len < PIM_PIM_MIN_LEN) { -    if (PIM_DEBUG_PIM_PACKETS) -      zlog_debug("PIM message size=%d shorter than minimum=%d", -		 pim_msg_len, PIM_PIM_MIN_LEN); -    return -1; -  } - -  if (header->ver != PIM_PROTO_VERSION) { -    if (PIM_DEBUG_PIM_PACKETS) -      zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d", -		 ifp->name, header->ver); -    return -1; -  } - -  /* save received checksum */ -  pim_checksum = header->checksum; - -  /* for computing checksum */ -  header->checksum = 0; - -  if (header->type == PIM_MSG_TYPE_REGISTER) -    { -      /* First 8 byte header checksum */ -      checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN); -      if (checksum != pim_checksum) -        { -          checksum = in_cksum (pim_msg, pim_msg_len); -          if (checksum != pim_checksum) -            { -              if (PIM_DEBUG_PIM_PACKETS) -                zlog_debug -                  ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", -                   ifp->name, pim_checksum, checksum); - -              return -1; -            } -        } -    } -  else -    { -      checksum = in_cksum (pim_msg, pim_msg_len); -      if (checksum != pim_checksum) -        { -          if (PIM_DEBUG_PIM_PACKETS) -            zlog_debug -              ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", -               ifp->name, pim_checksum, checksum); - -          return -1; -        } -    } - -  if (PIM_DEBUG_PIM_PACKETS) { -    pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str)); -    pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, sizeof(dst_str)); -    zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", -	       pim_pim_msgtype2str (header->type), src_str, dst_str, ifp->name, -	       ip_hdr->ip_ttl, header->ver, pim_msg_len, checksum); -    if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { -      pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); -    } -  } - -  switch (header->type) -    { -    case PIM_MSG_TYPE_HELLO: -      return pim_hello_recv (ifp, -			     ip_hdr->ip_src, -			     pim_msg + PIM_MSG_HEADER_LEN, -			     pim_msg_len - PIM_MSG_HEADER_LEN); -      break; -    case PIM_MSG_TYPE_REGISTER: -      return pim_register_recv (ifp, -				ip_hdr->ip_dst, -				ip_hdr->ip_src, -				pim_msg + PIM_MSG_HEADER_LEN, -				pim_msg_len - PIM_MSG_HEADER_LEN); -      break; -    case PIM_MSG_TYPE_REG_STOP: -      return pim_register_stop_recv (pim_msg + PIM_MSG_HEADER_LEN, -				     pim_msg_len - PIM_MSG_HEADER_LEN); -      break; -    case PIM_MSG_TYPE_JOIN_PRUNE: -      neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); -      if (!neigh) { -	if (PIM_DEBUG_PIM_PACKETS) -	  zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", -		     __FILE__, __PRETTY_FUNCTION__, -		     header->type, src_str, ifp->name); -	return -1; -      } -      pim_neighbor_timer_reset(neigh, neigh->holdtime); -      return pim_joinprune_recv(ifp, neigh, -				ip_hdr->ip_src, -				pim_msg + PIM_MSG_HEADER_LEN, -				pim_msg_len - PIM_MSG_HEADER_LEN); -      break; -    case PIM_MSG_TYPE_ASSERT: -      neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); -      if (!neigh) { -	if (PIM_DEBUG_PIM_PACKETS) -	  zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", -		     __FILE__, __PRETTY_FUNCTION__, -		     header->type, src_str, ifp->name); +	struct ip *ip_hdr; +	size_t ip_hlen; /* ip header length in bytes */ +	char src_str[INET_ADDRSTRLEN]; +	char dst_str[INET_ADDRSTRLEN]; +	uint8_t *pim_msg; +	int pim_msg_len; +	uint16_t pim_checksum; /* received checksum */ +	uint16_t checksum;     /* computed checksum */ +	struct pim_neighbor *neigh; +	struct pim_msg_header *header; + +	if (len < sizeof(*ip_hdr)) { +		if (PIM_DEBUG_PIM_PACKETS) +			zlog_debug( +				"PIM packet size=%zu shorter than minimum=%zu", +				len, sizeof(*ip_hdr)); +		return -1; +	} + +	ip_hdr = (struct ip *)buf; +	ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ + +	pim_msg = buf + ip_hlen; +	pim_msg_len = len - ip_hlen; + +	header = (struct pim_msg_header *)pim_msg; +	if (pim_msg_len < PIM_PIM_MIN_LEN) { +		if (PIM_DEBUG_PIM_PACKETS) +			zlog_debug( +				"PIM message size=%d shorter than minimum=%d", +				pim_msg_len, PIM_PIM_MIN_LEN); +		return -1; +	} + +	if (header->ver != PIM_PROTO_VERSION) { +		if (PIM_DEBUG_PIM_PACKETS) +			zlog_debug( +				"Ignoring PIM pkt from %s with unsupported version: %d", +				ifp->name, header->ver); +		return -1; +	} + +	/* save received checksum */ +	pim_checksum = header->checksum; + +	/* for computing checksum */ +	header->checksum = 0; + +	if (header->type == PIM_MSG_TYPE_REGISTER) { +		/* First 8 byte header checksum */ +		checksum = in_cksum(pim_msg, PIM_MSG_REGISTER_LEN); +		if (checksum != pim_checksum) { +			checksum = in_cksum(pim_msg, pim_msg_len); +			if (checksum != pim_checksum) { +				if (PIM_DEBUG_PIM_PACKETS) +					zlog_debug( +						"Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", +						ifp->name, pim_checksum, +						checksum); + +				return -1; +			} +		} +	} else { +		checksum = in_cksum(pim_msg, pim_msg_len); +		if (checksum != pim_checksum) { +			if (PIM_DEBUG_PIM_PACKETS) +				zlog_debug( +					"Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", +					ifp->name, pim_checksum, checksum); + +			return -1; +		} +	} + +	if (PIM_DEBUG_PIM_PACKETS) { +		pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, +			       sizeof(src_str)); +		pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, +			       sizeof(dst_str)); +		zlog_debug( +			"Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", +			pim_pim_msgtype2str(header->type), src_str, dst_str, +			ifp->name, ip_hdr->ip_ttl, header->ver, pim_msg_len, +			checksum); +		if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { +			pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); +		} +	} + +	switch (header->type) { +	case PIM_MSG_TYPE_HELLO: +		return pim_hello_recv(ifp, ip_hdr->ip_src, +				      pim_msg + PIM_MSG_HEADER_LEN, +				      pim_msg_len - PIM_MSG_HEADER_LEN); +		break; +	case PIM_MSG_TYPE_REGISTER: +		return pim_register_recv(ifp, ip_hdr->ip_dst, ip_hdr->ip_src, +					 pim_msg + PIM_MSG_HEADER_LEN, +					 pim_msg_len - PIM_MSG_HEADER_LEN); +		break; +	case PIM_MSG_TYPE_REG_STOP: +		return pim_register_stop_recv(pim_msg + PIM_MSG_HEADER_LEN, +					      pim_msg_len - PIM_MSG_HEADER_LEN); +		break; +	case PIM_MSG_TYPE_JOIN_PRUNE: +		neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); +		if (!neigh) { +			if (PIM_DEBUG_PIM_PACKETS) +				zlog_debug( +					"%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", +					__FILE__, __PRETTY_FUNCTION__, +					header->type, src_str, ifp->name); +			return -1; +		} +		pim_neighbor_timer_reset(neigh, neigh->holdtime); +		return pim_joinprune_recv(ifp, neigh, ip_hdr->ip_src, +					  pim_msg + PIM_MSG_HEADER_LEN, +					  pim_msg_len - PIM_MSG_HEADER_LEN); +		break; +	case PIM_MSG_TYPE_ASSERT: +		neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); +		if (!neigh) { +			if (PIM_DEBUG_PIM_PACKETS) +				zlog_debug( +					"%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", +					__FILE__, __PRETTY_FUNCTION__, +					header->type, src_str, ifp->name); +			return -1; +		} +		pim_neighbor_timer_reset(neigh, neigh->holdtime); +		return pim_assert_recv(ifp, neigh, ip_hdr->ip_src, +				       pim_msg + PIM_MSG_HEADER_LEN, +				       pim_msg_len - PIM_MSG_HEADER_LEN); +		break; +	default: +		if (PIM_DEBUG_PIM_PACKETS) { +			zlog_debug( +				"Recv PIM packet type %d which is not currently understood", +				header->type); +		} +		return -1; +	}  	return -1; -      } -      pim_neighbor_timer_reset(neigh, neigh->holdtime); -      return pim_assert_recv(ifp, neigh, -			     ip_hdr->ip_src, -			     pim_msg + PIM_MSG_HEADER_LEN, -			     pim_msg_len - PIM_MSG_HEADER_LEN); -      break; -    default: -      if (PIM_DEBUG_PIM_PACKETS) { -	zlog_debug("Recv PIM packet type %d which is not currently understood", -		   header->type); -      } -      return -1; -    } -  return -1;  }  static void pim_sock_read_on(struct interface *ifp);  static int pim_sock_read(struct thread *t)  { -  struct interface *ifp; -  struct pim_interface *pim_ifp; -  int fd; -  struct sockaddr_in from; -  struct sockaddr_in to; -  socklen_t fromlen = sizeof(from); -  socklen_t tolen = sizeof(to); -  uint8_t buf[PIM_PIM_BUFSIZE_READ]; -  int len; -  ifindex_t ifindex = -1; -  int result = -1; /* defaults to bad */ -  static long long count = 0; -  int cont = 1; - -  ifp = THREAD_ARG(t); -  fd = THREAD_FD(t); - -  pim_ifp = ifp->info; - -  while (cont) -    { -      len = pim_socket_recvfromto(fd, buf, sizeof(buf), -				  &from, &fromlen, -				  &to, &tolen, -				  &ifindex); -      if (len < 0) -	{ -	  if (errno == EINTR) -	    continue; -	  if (errno == EWOULDBLOCK || errno == EAGAIN) -            break; - -	  if (PIM_DEBUG_PIM_PACKETS) -	    zlog_debug ("Received errno: %d %s", errno, safe_strerror (errno)); -	  goto done; -	} +	struct interface *ifp; +	struct pim_interface *pim_ifp; +	int fd; +	struct sockaddr_in from; +	struct sockaddr_in to; +	socklen_t fromlen = sizeof(from); +	socklen_t tolen = sizeof(to); +	uint8_t buf[PIM_PIM_BUFSIZE_READ]; +	int len; +	ifindex_t ifindex = -1; +	int result = -1; /* defaults to bad */ +	static long long count = 0; +	int cont = 1; + +	ifp = THREAD_ARG(t); +	fd = THREAD_FD(t); + +	pim_ifp = ifp->info; + +	while (cont) { +		len = pim_socket_recvfromto(fd, buf, sizeof(buf), &from, +					    &fromlen, &to, &tolen, &ifindex); +		if (len < 0) { +			if (errno == EINTR) +				continue; +			if (errno == EWOULDBLOCK || errno == EAGAIN) +				break; + +			if (PIM_DEBUG_PIM_PACKETS) +				zlog_debug("Received errno: %d %s", errno, +					   safe_strerror(errno)); +			goto done; +		}  #ifdef PIM_CHECK_RECV_IFINDEX_SANITY -      /* ifindex sanity check */ -      if (ifindex != (int) ifp->ifindex) { -	char from_str[INET_ADDRSTRLEN]; -	char to_str[INET_ADDRSTRLEN]; -	struct interface *recv_ifp; - -	if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) -	  sprintf(from_str, "<from?>"); -	if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) -	  sprintf(to_str, "<to?>"); - -	recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); -	if (recv_ifp) { -	  zassert(ifindex == (int) recv_ifp->ifindex); -	} +		/* ifindex sanity check */ +		if (ifindex != (int)ifp->ifindex) { +			char from_str[INET_ADDRSTRLEN]; +			char to_str[INET_ADDRSTRLEN]; +			struct interface *recv_ifp; + +			if (!inet_ntop(AF_INET, &from.sin_addr, from_str, +				       sizeof(from_str))) +				sprintf(from_str, "<from?>"); +			if (!inet_ntop(AF_INET, &to.sin_addr, to_str, +				       sizeof(to_str))) +				sprintf(to_str, "<to?>"); + +			recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); +			if (recv_ifp) { +				zassert(ifindex == (int)recv_ifp->ifindex); +			}  #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH -	zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", -		  from_str, to_str, fd, -		  ifindex, recv_ifp ? recv_ifp->name : "<if-notfound>", -		  ifp->ifindex, ifp->name); +			zlog_warn( +				"Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", +				from_str, to_str, fd, ifindex, +				recv_ifp ? recv_ifp->name : "<if-notfound>", +				ifp->ifindex, ifp->name);  #endif -	goto done; -      } +			goto done; +		}  #endif -      int fail = pim_pim_packet(ifp, buf, len); -      if (fail) { -	if (PIM_DEBUG_PIM_PACKETS) -	  zlog_debug("%s: pim_pim_packet() return=%d", -		     __PRETTY_FUNCTION__, fail); -	goto done; -      } - -      count++; -      if (count % qpim_packet_process == 0) -        cont = 0; -    } +		int fail = pim_pim_packet(ifp, buf, len); +		if (fail) { +			if (PIM_DEBUG_PIM_PACKETS) +				zlog_debug("%s: pim_pim_packet() return=%d", +					   __PRETTY_FUNCTION__, fail); +			goto done; +		} + +		count++; +		if (count % qpim_packet_process == 0) +			cont = 0; +	} -  result = 0; /* good */ +	result = 0; /* good */ - done: -  pim_sock_read_on(ifp); +done: +	pim_sock_read_on(ifp); -  if (result) { -    ++pim_ifp->pim_ifstat_hello_recvfail; -  } +	if (result) { +		++pim_ifp->pim_ifstat_hello_recvfail; +	} -  return result; +	return result;  }  static void pim_sock_read_on(struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  zassert(ifp); -  zassert(ifp->info); +	zassert(ifp); +	zassert(ifp->info); -  pim_ifp = ifp->info; +	pim_ifp = ifp->info; -  if (PIM_DEBUG_PIM_TRACE_DETAIL) { -    zlog_debug("Scheduling READ event on PIM socket fd=%d", -	       pim_ifp->pim_sock_fd); -  } -  pim_ifp->t_pim_sock_read = NULL; -  thread_add_read(master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, -                  &pim_ifp->t_pim_sock_read); +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		zlog_debug("Scheduling READ event on PIM socket fd=%d", +			   pim_ifp->pim_sock_fd); +	} +	pim_ifp->t_pim_sock_read = NULL; +	thread_add_read(master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, +			&pim_ifp->t_pim_sock_read);  }  static int pim_sock_open(struct interface *ifp)  { -  int fd; -  struct pim_interface *pim_ifp = ifp->info; - -  fd = pim_socket_mcast(IPPROTO_PIM, pim_ifp->primary_address, ifp, 0 /* loop=false */); -  if (fd < 0) -    return -1; - -  if (pim_socket_join(fd, qpim_all_pim_routers_addr, pim_ifp->primary_address, ifp->ifindex)) { -    close(fd); -    return -2; -  } +	int fd; +	struct pim_interface *pim_ifp = ifp->info; + +	fd = pim_socket_mcast(IPPROTO_PIM, pim_ifp->primary_address, ifp, +			      0 /* loop=false */); +	if (fd < 0) +		return -1; + +	if (pim_socket_join(fd, qpim_all_pim_routers_addr, +			    pim_ifp->primary_address, ifp->ifindex)) { +		close(fd); +		return -2; +	} -  return fd; +	return fd;  }  void pim_ifstat_reset(struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  zassert(ifp); +	zassert(ifp); -  pim_ifp = ifp->info; -  if (!pim_ifp) { -    return; -  } +	pim_ifp = ifp->info; +	if (!pim_ifp) { +		return; +	} -  pim_ifp->pim_ifstat_start          = pim_time_monotonic_sec(); -  pim_ifp->pim_ifstat_hello_sent     = 0; -  pim_ifp->pim_ifstat_hello_sendfail = 0; -  pim_ifp->pim_ifstat_hello_recv     = 0; -  pim_ifp->pim_ifstat_hello_recvfail = 0; +	pim_ifp->pim_ifstat_start = pim_time_monotonic_sec(); +	pim_ifp->pim_ifstat_hello_sent = 0; +	pim_ifp->pim_ifstat_hello_sendfail = 0; +	pim_ifp->pim_ifstat_hello_recv = 0; +	pim_ifp->pim_ifstat_hello_recvfail = 0;  }  void pim_sock_reset(struct interface *ifp)  { -  struct pim_interface *pim_ifp; - -  zassert(ifp); -  zassert(ifp->info); - -  pim_ifp = ifp->info; - -  pim_ifp->primary_address = pim_find_primary_addr(ifp); - -  pim_ifp->pim_sock_fd       = -1; -  pim_ifp->pim_sock_creation = 0; -  pim_ifp->t_pim_sock_read   = NULL; - -  pim_ifp->t_pim_hello_timer          = NULL; -  pim_ifp->pim_hello_period           = PIM_DEFAULT_HELLO_PERIOD; -  pim_ifp->pim_default_holdtime       = -1; /* unset: means 3.5 * pim_hello_period */ -  pim_ifp->pim_triggered_hello_delay  = PIM_DEFAULT_TRIGGERED_HELLO_DELAY; -  pim_ifp->pim_dr_priority            = PIM_DEFAULT_DR_PRIORITY; -  pim_ifp->pim_propagation_delay_msec = PIM_DEFAULT_PROPAGATION_DELAY_MSEC; -  pim_ifp->pim_override_interval_msec = PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; -  if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) { -    PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); -  } -  else { -    PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); -  } - -  /* neighbors without lan_delay */ -  pim_ifp->pim_number_of_nonlandelay_neighbors = 0; -  pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0; -  pim_ifp->pim_neighbors_highest_override_interval_msec = 0; - -  /* DR Election */ -  pim_ifp->pim_dr_election_last          = 0; /* timestamp */ -  pim_ifp->pim_dr_election_count         = 0; -  pim_ifp->pim_dr_election_changes       = 0; -  pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */ -  pim_ifp->pim_dr_addr                   = pim_ifp->primary_address; - -  pim_ifstat_reset(ifp); +	struct pim_interface *pim_ifp; + +	zassert(ifp); +	zassert(ifp->info); + +	pim_ifp = ifp->info; + +	pim_ifp->primary_address = pim_find_primary_addr(ifp); + +	pim_ifp->pim_sock_fd = -1; +	pim_ifp->pim_sock_creation = 0; +	pim_ifp->t_pim_sock_read = NULL; + +	pim_ifp->t_pim_hello_timer = NULL; +	pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; +	pim_ifp->pim_default_holdtime = +		-1; /* unset: means 3.5 * pim_hello_period */ +	pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY; +	pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; +	pim_ifp->pim_propagation_delay_msec = +		PIM_DEFAULT_PROPAGATION_DELAY_MSEC; +	pim_ifp->pim_override_interval_msec = +		PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; +	if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) { +		PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); +	} else { +		PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); +	} + +	/* neighbors without lan_delay */ +	pim_ifp->pim_number_of_nonlandelay_neighbors = 0; +	pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0; +	pim_ifp->pim_neighbors_highest_override_interval_msec = 0; + +	/* DR Election */ +	pim_ifp->pim_dr_election_last = 0; /* timestamp */ +	pim_ifp->pim_dr_election_count = 0; +	pim_ifp->pim_dr_election_changes = 0; +	pim_ifp->pim_dr_num_nondrpri_neighbors = +		0; /* neighbors without dr_pri */ +	pim_ifp->pim_dr_addr = pim_ifp->primary_address; + +	pim_ifstat_reset(ifp);  }  static uint16_t ip_id = 0; -static int -pim_msg_send_frame (int fd, char *buf, size_t len, -		    struct sockaddr *dst, size_t salen) +static int pim_msg_send_frame(int fd, char *buf, size_t len, +			      struct sockaddr *dst, size_t salen)  { -  struct ip *ip = (struct ip *)buf; - -  while (sendto (fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) -    { -      char dst_str[INET_ADDRSTRLEN]; - -      switch (errno) -	{ -	case EMSGSIZE: -	  { -	    size_t hdrsize = sizeof (struct ip); -	    size_t newlen1 = ((len - hdrsize) / 2 ) & 0xFFF8; -	    size_t sendlen = newlen1 + hdrsize; -	    size_t offset = ntohs (ip->ip_off); - -	    ip->ip_len = htons (sendlen); -	    ip->ip_off = htons (offset | IP_MF); -	    if (pim_msg_send_frame (fd, buf, sendlen, dst, salen) == 0) -	      { -		struct ip *ip2 = (struct ip *)(buf + newlen1); -		size_t newlen2 = len - sendlen; -		sendlen = newlen2 + hdrsize; - -		memcpy (ip2, ip, hdrsize); -		ip2->ip_len = htons (sendlen); -		ip2->ip_off = htons (offset + (newlen1 >> 3)); -		return pim_msg_send_frame (fd, (char *)ip2, sendlen, dst, salen); -	      } -	  } - -	  return -1; -	  break; -	default: -	  if (PIM_DEBUG_PIM_PACKETS) -	    { -	      pim_inet4_dump ("<dst?>", ip->ip_dst, dst_str, sizeof (dst_str)); -	      zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", -			 __PRETTY_FUNCTION__, -			 dst_str, fd, len, -			 errno, safe_strerror(errno)); -	    } -	  return -1; -	  break; +	struct ip *ip = (struct ip *)buf; + +	while (sendto(fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) { +		char dst_str[INET_ADDRSTRLEN]; + +		switch (errno) { +		case EMSGSIZE: { +			size_t hdrsize = sizeof(struct ip); +			size_t newlen1 = ((len - hdrsize) / 2) & 0xFFF8; +			size_t sendlen = newlen1 + hdrsize; +			size_t offset = ntohs(ip->ip_off); + +			ip->ip_len = htons(sendlen); +			ip->ip_off = htons(offset | IP_MF); +			if (pim_msg_send_frame(fd, buf, sendlen, dst, salen) +			    == 0) { +				struct ip *ip2 = (struct ip *)(buf + newlen1); +				size_t newlen2 = len - sendlen; +				sendlen = newlen2 + hdrsize; + +				memcpy(ip2, ip, hdrsize); +				ip2->ip_len = htons(sendlen); +				ip2->ip_off = htons(offset + (newlen1 >> 3)); +				return pim_msg_send_frame(fd, (char *)ip2, +							  sendlen, dst, salen); +			} +		} + +			return -1; +			break; +		default: +			if (PIM_DEBUG_PIM_PACKETS) { +				pim_inet4_dump("<dst?>", ip->ip_dst, dst_str, +					       sizeof(dst_str)); +				zlog_warn( +					"%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", +					__PRETTY_FUNCTION__, dst_str, fd, len, +					errno, safe_strerror(errno)); +			} +			return -1; +			break; +		}  	} -    } -  return 0; +	return 0;  } -int -pim_msg_send(int fd, struct in_addr src, -	     struct in_addr dst, uint8_t *pim_msg, -	     int pim_msg_size, const char *ifname) +int pim_msg_send(int fd, struct in_addr src, struct in_addr dst, +		 uint8_t *pim_msg, int pim_msg_size, const char *ifname)  { -  struct sockaddr_in to; -  socklen_t          tolen; -  unsigned char      buffer[10000]; -  unsigned char      *msg_start; -  uint8_t            ttl = MAXTTL; -  struct pim_msg_header *header; -  struct ip *ip; - -  memset (buffer, 0, 10000); -  int sendlen = sizeof (struct ip) + pim_msg_size; - -  msg_start = buffer + sizeof (struct ip); -  memcpy (msg_start, pim_msg, pim_msg_size); - -  header = (struct pim_msg_header *)pim_msg; -  /* -   * Omnios apparently doesn't have a #define for IP default -   * ttl that is the same as all other platforms. -   */ +	struct sockaddr_in to; +	socklen_t tolen; +	unsigned char buffer[10000]; +	unsigned char *msg_start; +	uint8_t ttl = MAXTTL; +	struct pim_msg_header *header; +	struct ip *ip; + +	memset(buffer, 0, 10000); +	int sendlen = sizeof(struct ip) + pim_msg_size; + +	msg_start = buffer + sizeof(struct ip); +	memcpy(msg_start, pim_msg, pim_msg_size); + +	header = (struct pim_msg_header *)pim_msg; +/* + * Omnios apparently doesn't have a #define for IP default + * ttl that is the same as all other platforms. + */  #ifndef IPDEFTTL  #define IPDEFTTL   64  #endif -  /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */ -  switch (header->type) -    { -    case PIM_MSG_TYPE_HELLO: -    case PIM_MSG_TYPE_JOIN_PRUNE: -    case PIM_MSG_TYPE_BOOTSTRAP: -    case PIM_MSG_TYPE_ASSERT: -      ttl = 1; -      break; -    case PIM_MSG_TYPE_REGISTER: -    case PIM_MSG_TYPE_REG_STOP: -    case PIM_MSG_TYPE_GRAFT: -    case PIM_MSG_TYPE_GRAFT_ACK: -    case PIM_MSG_TYPE_CANDIDATE: -      ttl = IPDEFTTL; -      break; -    default: -      ttl = MAXTTL; -      break; -    } - -  ip = (struct ip *) buffer; -  ip->ip_id = htons (++ip_id); -  ip->ip_hl = 5; -  ip->ip_v = 4; -  ip->ip_p = PIM_IP_PROTO_PIM; -  ip->ip_src = src; -  ip->ip_dst = dst; -  ip->ip_ttl = ttl; -  ip->ip_len = htons (sendlen); - -  if (PIM_DEBUG_PIM_PACKETS) { -    struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; -    char dst_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str)); -    zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x", -	       __PRETTY_FUNCTION__, -	       dst_str, ifname, pim_msg_size, -	       header->checksum); -  } - -  memset(&to, 0, sizeof(to)); -  to.sin_family = AF_INET; -  to.sin_addr = dst; -  tolen = sizeof(to); - -  if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { -    pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); -  } - -  pim_msg_send_frame (fd, (char *)buffer, sendlen, -		      (struct sockaddr *)&to, tolen); -  return 0; +	/* TTL for packets destine to ALL-PIM-ROUTERS is 1 */ +	switch (header->type) { +	case PIM_MSG_TYPE_HELLO: +	case PIM_MSG_TYPE_JOIN_PRUNE: +	case PIM_MSG_TYPE_BOOTSTRAP: +	case PIM_MSG_TYPE_ASSERT: +		ttl = 1; +		break; +	case PIM_MSG_TYPE_REGISTER: +	case PIM_MSG_TYPE_REG_STOP: +	case PIM_MSG_TYPE_GRAFT: +	case PIM_MSG_TYPE_GRAFT_ACK: +	case PIM_MSG_TYPE_CANDIDATE: +		ttl = IPDEFTTL; +		break; +	default: +		ttl = MAXTTL; +		break; +	} + +	ip = (struct ip *)buffer; +	ip->ip_id = htons(++ip_id); +	ip->ip_hl = 5; +	ip->ip_v = 4; +	ip->ip_p = PIM_IP_PROTO_PIM; +	ip->ip_src = src; +	ip->ip_dst = dst; +	ip->ip_ttl = ttl; +	ip->ip_len = htons(sendlen); + +	if (PIM_DEBUG_PIM_PACKETS) { +		struct pim_msg_header *header = +			(struct pim_msg_header *)pim_msg; +		char dst_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str)); +		zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x", +			   __PRETTY_FUNCTION__, dst_str, ifname, pim_msg_size, +			   header->checksum); +	} + +	memset(&to, 0, sizeof(to)); +	to.sin_family = AF_INET; +	to.sin_addr = dst; +	tolen = sizeof(to); + +	if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { +		pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); +	} + +	pim_msg_send_frame(fd, (char *)buffer, sendlen, (struct sockaddr *)&to, +			   tolen); +	return 0;  } -static int hello_send(struct interface *ifp, -		      uint16_t holdtime) +static int hello_send(struct interface *ifp, uint16_t holdtime)  { -  uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE]; -  struct pim_interface *pim_ifp; -  int pim_tlv_size; -  int pim_msg_size; - -  pim_ifp = ifp->info; - -  if (PIM_DEBUG_PIM_HELLO) { -    char dst_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str)); -    zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d", -	       __PRETTY_FUNCTION__, -	       dst_str, ifp->name, -	       holdtime, -	       pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec, -	       PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options), -	       pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, -	       listcount(ifp->connected)); -  } - -  pim_tlv_size = pim_hello_build_tlv(ifp, -				     pim_msg + PIM_PIM_MIN_LEN, -				     sizeof(pim_msg) - PIM_PIM_MIN_LEN, -				     holdtime, -				     pim_ifp->pim_dr_priority, -				     pim_ifp->pim_generation_id, -				     pim_ifp->pim_propagation_delay_msec, -				     pim_ifp->pim_override_interval_msec, -				     PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); -  if (pim_tlv_size < 0) { -    return -1; -  } - -  pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; - -  zassert(pim_msg_size >= PIM_PIM_MIN_LEN); -  zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); - -  pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO); - -  if (pim_msg_send(pim_ifp->pim_sock_fd, -		   pim_ifp->primary_address, -		   qpim_all_pim_routers_addr, -		   pim_msg, -		   pim_msg_size, -		   ifp->name)) { -    if (PIM_DEBUG_PIM_HELLO) { -      zlog_debug("%s: could not send PIM message on interface %s", -		 __PRETTY_FUNCTION__, ifp->name); -    } -    return -2; -  } - -  return 0; +	uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE]; +	struct pim_interface *pim_ifp; +	int pim_tlv_size; +	int pim_msg_size; + +	pim_ifp = ifp->info; + +	if (PIM_DEBUG_PIM_HELLO) { +		char dst_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, +			       sizeof(dst_str)); +		zlog_debug( +			"%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d", +			__PRETTY_FUNCTION__, dst_str, ifp->name, holdtime, +			pim_ifp->pim_propagation_delay_msec, +			pim_ifp->pim_override_interval_msec, +			PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION( +				pim_ifp->options), +			pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, +			listcount(ifp->connected)); +	} + +	pim_tlv_size = pim_hello_build_tlv( +		ifp, pim_msg + PIM_PIM_MIN_LEN, +		sizeof(pim_msg) - PIM_PIM_MIN_LEN, holdtime, +		pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, +		pim_ifp->pim_propagation_delay_msec, +		pim_ifp->pim_override_interval_msec, +		PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); +	if (pim_tlv_size < 0) { +		return -1; +	} + +	pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; + +	zassert(pim_msg_size >= PIM_PIM_MIN_LEN); +	zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); + +	pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO); + +	if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, +			 qpim_all_pim_routers_addr, pim_msg, pim_msg_size, +			 ifp->name)) { +		if (PIM_DEBUG_PIM_HELLO) { +			zlog_debug( +				"%s: could not send PIM message on interface %s", +				__PRETTY_FUNCTION__, ifp->name); +		} +		return -2; +	} + +	return 0;  } -static int pim_hello_send(struct interface *ifp, -			  uint16_t holdtime) +static int pim_hello_send(struct interface *ifp, uint16_t holdtime)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  zassert(ifp); -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	zassert(ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  if (if_is_loopback (ifp)) -    return 0; +	if (if_is_loopback(ifp)) +		return 0; -  if (hello_send(ifp, holdtime)) { -    ++pim_ifp->pim_ifstat_hello_sendfail; +	if (hello_send(ifp, holdtime)) { +		++pim_ifp->pim_ifstat_hello_sendfail; -    if (PIM_DEBUG_PIM_HELLO) { -      zlog_warn("Could not send PIM hello on interface %s", -		ifp->name); -    } -    return -1; -  } +		if (PIM_DEBUG_PIM_HELLO) { +			zlog_warn("Could not send PIM hello on interface %s", +				  ifp->name); +		} +		return -1; +	} -  ++pim_ifp->pim_ifstat_hello_sent; +	++pim_ifp->pim_ifstat_hello_sent; -  return 0; +	return 0;  }  static void hello_resched(struct interface *ifp)  { -  struct pim_interface *pim_ifp; - -  zassert(ifp); -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  if (PIM_DEBUG_PIM_HELLO) { -    zlog_debug("Rescheduling %d sec hello on interface %s", -	       pim_ifp->pim_hello_period, ifp->name); -  } -  THREAD_OFF(pim_ifp->t_pim_hello_timer); -  thread_add_timer(master, on_pim_hello_send, ifp, pim_ifp->pim_hello_period, -                   &pim_ifp->t_pim_hello_timer); +	struct pim_interface *pim_ifp; + +	zassert(ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	if (PIM_DEBUG_PIM_HELLO) { +		zlog_debug("Rescheduling %d sec hello on interface %s", +			   pim_ifp->pim_hello_period, ifp->name); +	} +	THREAD_OFF(pim_ifp->t_pim_hello_timer); +	thread_add_timer(master, on_pim_hello_send, ifp, +			 pim_ifp->pim_hello_period, +			 &pim_ifp->t_pim_hello_timer);  }  /* @@ -711,22 +714,22 @@ static void hello_resched(struct interface *ifp)   */  static int on_pim_hello_send(struct thread *t)  { -  struct pim_interface *pim_ifp; -  struct interface *ifp; +	struct pim_interface *pim_ifp; +	struct interface *ifp; -  ifp = THREAD_ARG(t); +	ifp = THREAD_ARG(t); -  pim_ifp = ifp->info; +	pim_ifp = ifp->info; -  /* -   * Schedule next hello -   */ -  hello_resched(ifp); +	/* +	 * Schedule next hello +	 */ +	hello_resched(ifp); -  /* -   * Send hello -   */ -  return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); +	/* +	 * Send hello +	 */ +	return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));  }  /* @@ -740,21 +743,21 @@ static int on_pim_hello_send(struct thread *t)   */  void pim_hello_restart_now(struct interface *ifp)  { -  struct pim_interface *pim_ifp; +	struct pim_interface *pim_ifp; -  zassert(ifp); -  pim_ifp = ifp->info; -  zassert(pim_ifp); +	zassert(ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); -  /* -   * Reset next hello timer -   */ -  hello_resched(ifp); +	/* +	 * Reset next hello timer +	 */ +	hello_resched(ifp); -  /* -   * Immediately send hello -   */ -  pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); +	/* +	 * Immediately send hello +	 */ +	pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));  }  /* @@ -768,105 +771,109 @@ void pim_hello_restart_now(struct interface *ifp)   */  void pim_hello_restart_triggered(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  int triggered_hello_delay_msec; -  int random_msec; - -  zassert(ifp); -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  /* -   * There exists situations where we have the a RPF out this -   * interface, but we haven't formed a neighbor yet.  This -   * happens especially during interface flaps.  While -   * we would like to handle this more gracefully in other -   * parts of the code.  In order to get us up and running -   * let's just send the hello immediate'ish -   * This should be revisited when we get nexthop tracking -   * in and when we have a better handle on safely -   * handling the rpf information for upstreams that -   * we cannot legally reach yet. -   */ -  triggered_hello_delay_msec = 1; -  //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay; - -  if (pim_ifp->t_pim_hello_timer) { -    long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer); -    if (remain_msec <= triggered_hello_delay_msec) { -      /* Rescheduling hello would increase the delay, then it's faster -	 to just wait for the scheduled periodic hello. */ -      return; -    } - -    THREAD_OFF(pim_ifp->t_pim_hello_timer); -  } - -  random_msec = triggered_hello_delay_msec; -  //random_msec = random() % (triggered_hello_delay_msec + 1); - -  if (PIM_DEBUG_PIM_HELLO) { -    zlog_debug("Scheduling %d msec triggered hello on interface %s", -	       random_msec, ifp->name); -  } - -  thread_add_timer_msec(master, on_pim_hello_send, ifp, random_msec, -                        &pim_ifp->t_pim_hello_timer); +	struct pim_interface *pim_ifp; +	int triggered_hello_delay_msec; +	int random_msec; + +	zassert(ifp); +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	/* +	 * There exists situations where we have the a RPF out this +	 * interface, but we haven't formed a neighbor yet.  This +	 * happens especially during interface flaps.  While +	 * we would like to handle this more gracefully in other +	 * parts of the code.  In order to get us up and running +	 * let's just send the hello immediate'ish +	 * This should be revisited when we get nexthop tracking +	 * in and when we have a better handle on safely +	 * handling the rpf information for upstreams that +	 * we cannot legally reach yet. +	 */ +	triggered_hello_delay_msec = 1; +	// triggered_hello_delay_msec = 1000 * +	// pim_ifp->pim_triggered_hello_delay; + +	if (pim_ifp->t_pim_hello_timer) { +		long remain_msec = +			pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer); +		if (remain_msec <= triggered_hello_delay_msec) { +			/* Rescheduling hello would increase the delay, then +			   it's faster +			   to just wait for the scheduled periodic hello. */ +			return; +		} + +		THREAD_OFF(pim_ifp->t_pim_hello_timer); +	} + +	random_msec = triggered_hello_delay_msec; +	// random_msec = random() % (triggered_hello_delay_msec + 1); + +	if (PIM_DEBUG_PIM_HELLO) { +		zlog_debug("Scheduling %d msec triggered hello on interface %s", +			   random_msec, ifp->name); +	} + +	thread_add_timer_msec(master, on_pim_hello_send, ifp, random_msec, +			      &pim_ifp->t_pim_hello_timer);  }  int pim_sock_add(struct interface *ifp)  { -  struct pim_interface *pim_ifp; -  uint32_t old_genid; - -  pim_ifp = ifp->info; -  zassert(pim_ifp); - -  if (pim_ifp->pim_sock_fd >= 0) { -    if (PIM_DEBUG_PIM_PACKETS) -      zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s", -		 pim_ifp->pim_sock_fd, ifp->name); -    return -1; -  } - -  pim_ifp->pim_sock_fd = pim_sock_open(ifp); -  if (pim_ifp->pim_sock_fd < 0) { -    if (PIM_DEBUG_PIM_PACKETS) -      zlog_debug("Could not open PIM socket on interface %s", -		 ifp->name); -    return -2; -  } - -  pim_socket_ip_hdr (pim_ifp->pim_sock_fd); - -  pim_ifp->t_pim_sock_read   = NULL; -  pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); - -  /* -   * Just ensure that the new generation id -   * actually chooses something different. -   * Actually ran across a case where this -   * happened, pre-switch to random(). -   * While this is unlikely to happen now -   * let's make sure it doesn't. -   */ -  old_genid = pim_ifp->pim_generation_id; - -  while (old_genid == pim_ifp->pim_generation_id) -    pim_ifp->pim_generation_id = random(); - -  zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", -	    ifp->name, ifp->ifindex); - -  /* -   * Start receiving PIM messages -   */ -  pim_sock_read_on(ifp); - -  /* -   * Start sending PIM hello's -   */ -  pim_hello_restart_triggered(ifp); - -  return 0; +	struct pim_interface *pim_ifp; +	uint32_t old_genid; + +	pim_ifp = ifp->info; +	zassert(pim_ifp); + +	if (pim_ifp->pim_sock_fd >= 0) { +		if (PIM_DEBUG_PIM_PACKETS) +			zlog_debug( +				"Can't recreate existing PIM socket fd=%d for interface %s", +				pim_ifp->pim_sock_fd, ifp->name); +		return -1; +	} + +	pim_ifp->pim_sock_fd = pim_sock_open(ifp); +	if (pim_ifp->pim_sock_fd < 0) { +		if (PIM_DEBUG_PIM_PACKETS) +			zlog_debug("Could not open PIM socket on interface %s", +				   ifp->name); +		return -2; +	} + +	pim_socket_ip_hdr(pim_ifp->pim_sock_fd); + +	pim_ifp->t_pim_sock_read = NULL; +	pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); + +	/* +	 * Just ensure that the new generation id +	 * actually chooses something different. +	 * Actually ran across a case where this +	 * happened, pre-switch to random(). +	 * While this is unlikely to happen now +	 * let's make sure it doesn't. +	 */ +	old_genid = pim_ifp->pim_generation_id; + +	while (old_genid == pim_ifp->pim_generation_id) +		pim_ifp->pim_generation_id = random(); + +	zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", ifp->name, +		  ifp->ifindex); + +	/* +	 * Start receiving PIM messages +	 */ +	pim_sock_read_on(ifp); + +	/* +	 * Start sending PIM hello's +	 */ +	pim_hello_restart_triggered(ifp); + +	return 0;  } diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 7e2872184a..e930ab7c2d 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -36,15 +36,15 @@  #define PIM_DEFAULT_T_PERIODIC                   (60)   /* RFC 4601: 4.11.  Timer Values */  enum pim_msg_type { -  PIM_MSG_TYPE_HELLO = 0, -  PIM_MSG_TYPE_REGISTER, -  PIM_MSG_TYPE_REG_STOP, -  PIM_MSG_TYPE_JOIN_PRUNE, -  PIM_MSG_TYPE_BOOTSTRAP, -  PIM_MSG_TYPE_ASSERT, -  PIM_MSG_TYPE_GRAFT, -  PIM_MSG_TYPE_GRAFT_ACK, -  PIM_MSG_TYPE_CANDIDATE +	PIM_MSG_TYPE_HELLO = 0, +	PIM_MSG_TYPE_REGISTER, +	PIM_MSG_TYPE_REG_STOP, +	PIM_MSG_TYPE_JOIN_PRUNE, +	PIM_MSG_TYPE_BOOTSTRAP, +	PIM_MSG_TYPE_ASSERT, +	PIM_MSG_TYPE_GRAFT, +	PIM_MSG_TYPE_GRAFT_ACK, +	PIM_MSG_TYPE_CANDIDATE  };  void pim_ifstat_reset(struct interface *ifp); @@ -56,11 +56,7 @@ void pim_hello_restart_triggered(struct interface *ifp);  int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len); -int pim_msg_send(int fd, -		 struct in_addr src, -		 struct in_addr dst, -		 uint8_t *pim_msg, -		 int pim_msg_size, -		 const char *ifname); +int pim_msg_send(int fd, struct in_addr src, struct in_addr dst, +		 uint8_t *pim_msg, int pim_msg_size, const char *ifname);  #endif /* PIM_PIM_H */ diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 682a6401ca..1cbe1dcf7f 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -46,179 +46,173 @@  struct thread *send_test_packet_timer = NULL; -void -pim_register_join (struct pim_upstream *up) +void pim_register_join(struct pim_upstream *up)  { -  if (pim_is_grp_ssm (up->sg.grp)) -    { -      if (PIM_DEBUG_PIM_EVENTS) -	zlog_debug ("%s register setup skipped as group is SSM", up->sg_str); -      return; -    } - -  pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); -  up->reg_state = PIM_REG_JOIN; +	if (pim_is_grp_ssm(up->sg.grp)) { +		if (PIM_DEBUG_PIM_EVENTS) +			zlog_debug("%s register setup skipped as group is SSM", +				   up->sg_str); +		return; +	} + +	pim_channel_add_oif(up->channel_oil, pim_regiface, +			    PIM_OIF_FLAG_PROTO_PIM); +	up->reg_state = PIM_REG_JOIN;  } -void -pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, -			struct in_addr src, struct in_addr originator) +void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg, +			    struct in_addr src, struct in_addr originator)  { -  struct pim_interface *pinfo; -  unsigned char buffer[10000]; -  unsigned int b1length = 0; -  unsigned int length; -  uint8_t *b1; -  struct prefix p; - -  if (PIM_DEBUG_PIM_REG) -    { -      zlog_debug ("Sending Register stop for %s to %s on %s", -		  pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name); -    } - -  memset (buffer, 0, 10000); -  b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; - -  length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp); -  b1length += length; -  b1 += length; - -  p.family = AF_INET; -  p.u.prefix4 = sg->src; -  p.prefixlen = 32; -  length = pim_encode_addr_ucast (b1, &p); -  b1length += length; - -  pim_msg_build_header (buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, PIM_MSG_TYPE_REG_STOP); - -  pinfo = (struct pim_interface *)ifp->info; -  if (!pinfo) -    { -      if (PIM_DEBUG_PIM_TRACE) -        zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__); -      return; -    } -  if (pim_msg_send (pinfo->pim_sock_fd, src, originator, -		    buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, -		    ifp->name)) -    { -      if (PIM_DEBUG_PIM_TRACE) -	{ -	  zlog_debug ("%s: could not send PIM register stop message on interface %s", -		      __PRETTY_FUNCTION__, ifp->name); +	struct pim_interface *pinfo; +	unsigned char buffer[10000]; +	unsigned int b1length = 0; +	unsigned int length; +	uint8_t *b1; +	struct prefix p; + +	if (PIM_DEBUG_PIM_REG) { +		zlog_debug("Sending Register stop for %s to %s on %s", +			   pim_str_sg_dump(sg), inet_ntoa(originator), +			   ifp->name); +	} + +	memset(buffer, 0, 10000); +	b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; + +	length = pim_encode_addr_group(b1, AFI_IP, 0, 0, sg->grp); +	b1length += length; +	b1 += length; + +	p.family = AF_INET; +	p.u.prefix4 = sg->src; +	p.prefixlen = 32; +	length = pim_encode_addr_ucast(b1, &p); +	b1length += length; + +	pim_msg_build_header(buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, +			     PIM_MSG_TYPE_REG_STOP); + +	pinfo = (struct pim_interface *)ifp->info; +	if (!pinfo) { +		if (PIM_DEBUG_PIM_TRACE) +			zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__); +		return;  	} -    } -  ++pinfo->pim_ifstat_reg_stop_send; +	if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer, +			 b1length + PIM_MSG_REGISTER_STOP_LEN, ifp->name)) { +		if (PIM_DEBUG_PIM_TRACE) { +			zlog_debug( +				"%s: could not send PIM register stop message on interface %s", +				__PRETTY_FUNCTION__, ifp->name); +		} +	} +	++pinfo->pim_ifstat_reg_stop_send;  } -int -pim_register_stop_recv (uint8_t *buf, int buf_size) +int pim_register_stop_recv(uint8_t *buf, int buf_size)  { -  struct pim_upstream *upstream = NULL; -  struct prefix source; -  struct prefix_sg sg; -  int l; - -  memset (&sg, 0, sizeof (struct prefix_sg)); -  l = pim_parse_addr_group (&sg, buf, buf_size); -  buf += l; -  buf_size -= l; -  pim_parse_addr_ucast (&source, buf, buf_size); -  sg.src = source.u.prefix4; - -  upstream = pim_upstream_find (&sg); -  if (!upstream) -    { -      return 0; -    } - -  if (PIM_DEBUG_PIM_REG) -    zlog_debug ("Received Register stop for %s", -		upstream->sg_str); - -  switch (upstream->reg_state) -    { -    case PIM_REG_NOINFO: -    case PIM_REG_PRUNE: -      return 0; -      break; -    case PIM_REG_JOIN: -      upstream->reg_state = PIM_REG_PRUNE; -      pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); -      pim_upstream_start_register_stop_timer (upstream, 0); -      break; -    case PIM_REG_JOIN_PENDING: -      upstream->reg_state = PIM_REG_PRUNE; -      pim_upstream_start_register_stop_timer (upstream, 0); -      return 0; -      break; -    } - -  return 0; +	struct pim_upstream *upstream = NULL; +	struct prefix source; +	struct prefix_sg sg; +	int l; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	l = pim_parse_addr_group(&sg, buf, buf_size); +	buf += l; +	buf_size -= l; +	pim_parse_addr_ucast(&source, buf, buf_size); +	sg.src = source.u.prefix4; + +	upstream = pim_upstream_find(&sg); +	if (!upstream) { +		return 0; +	} + +	if (PIM_DEBUG_PIM_REG) +		zlog_debug("Received Register stop for %s", upstream->sg_str); + +	switch (upstream->reg_state) { +	case PIM_REG_NOINFO: +	case PIM_REG_PRUNE: +		return 0; +		break; +	case PIM_REG_JOIN: +		upstream->reg_state = PIM_REG_PRUNE; +		pim_channel_del_oif(upstream->channel_oil, pim_regiface, +				    PIM_OIF_FLAG_PROTO_PIM); +		pim_upstream_start_register_stop_timer(upstream, 0); +		break; +	case PIM_REG_JOIN_PENDING: +		upstream->reg_state = PIM_REG_PRUNE; +		pim_upstream_start_register_stop_timer(upstream, 0); +		return 0; +		break; +	} + +	return 0;  } -void -pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up) +void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, +		       struct pim_rpf *rpg, int null_register, +		       struct pim_upstream *up)  { -  unsigned char buffer[10000]; -  unsigned char *b1; -  struct pim_interface *pinfo; -  struct interface *ifp; - -  if (PIM_DEBUG_PIM_REG) -    { -       zlog_debug ("Sending %s %sRegister Packet to %s", -		   up->sg_str, null_register ? "NULL " : "", -                   inet_ntoa (rpg->rpf_addr.u.prefix4)); -    } - -  ifp = rpg->source_nexthop.interface; -  if (!ifp) -    { -      if (PIM_DEBUG_PIM_REG) -        zlog_debug ("%s: No interface to transmit register on", __PRETTY_FUNCTION__); -      return; -    } -  pinfo = (struct pim_interface *)ifp->info; -  if (!pinfo) { -    if (PIM_DEBUG_PIM_REG) -      zlog_debug("%s: Interface: %s not configured for pim to trasmit on!\n", __PRETTY_FUNCTION__, ifp->name); -    return; -  } - -  if (PIM_DEBUG_PIM_REG) -    { -      char rp_str[INET_ADDRSTRLEN]; -      strncpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4), INET_ADDRSTRLEN-1); -      zlog_debug ("%s: Sending %s %sRegister Packet to %s on %s", -              __PRETTY_FUNCTION__, up->sg_str, -              null_register ? "NULL " : "", rp_str, ifp->name); -    } - -  memset(buffer, 0, 10000); -  b1 = buffer + PIM_MSG_HEADER_LEN; -  *b1 |= null_register << 6; -  b1 = buffer + PIM_MSG_REGISTER_LEN; - -  memcpy(b1, (const unsigned char *)buf, buf_size); - -  pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); - -  ++pinfo->pim_ifstat_reg_send; - -  if (pim_msg_send(pinfo->pim_sock_fd, -		   src, -		   rpg->rpf_addr.u.prefix4, -		   buffer, -		   buf_size + PIM_MSG_REGISTER_LEN, -		   ifp->name)) { -    if (PIM_DEBUG_PIM_TRACE) { -      zlog_debug("%s: could not send PIM register message on interface %s", -		 __PRETTY_FUNCTION__, ifp->name); -    } -    return; -  } +	unsigned char buffer[10000]; +	unsigned char *b1; +	struct pim_interface *pinfo; +	struct interface *ifp; + +	if (PIM_DEBUG_PIM_REG) { +		zlog_debug("Sending %s %sRegister Packet to %s", up->sg_str, +			   null_register ? "NULL " : "", +			   inet_ntoa(rpg->rpf_addr.u.prefix4)); +	} + +	ifp = rpg->source_nexthop.interface; +	if (!ifp) { +		if (PIM_DEBUG_PIM_REG) +			zlog_debug("%s: No interface to transmit register on", +				   __PRETTY_FUNCTION__); +		return; +	} +	pinfo = (struct pim_interface *)ifp->info; +	if (!pinfo) { +		if (PIM_DEBUG_PIM_REG) +			zlog_debug( +				"%s: Interface: %s not configured for pim to trasmit on!\n", +				__PRETTY_FUNCTION__, ifp->name); +		return; +	} + +	if (PIM_DEBUG_PIM_REG) { +		char rp_str[INET_ADDRSTRLEN]; +		strncpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4), +			INET_ADDRSTRLEN - 1); +		zlog_debug("%s: Sending %s %sRegister Packet to %s on %s", +			   __PRETTY_FUNCTION__, up->sg_str, +			   null_register ? "NULL " : "", rp_str, ifp->name); +	} + +	memset(buffer, 0, 10000); +	b1 = buffer + PIM_MSG_HEADER_LEN; +	*b1 |= null_register << 6; +	b1 = buffer + PIM_MSG_REGISTER_LEN; + +	memcpy(b1, (const unsigned char *)buf, buf_size); + +	pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, +			     PIM_MSG_TYPE_REGISTER); + +	++pinfo->pim_ifstat_reg_send; + +	if (pim_msg_send(pinfo->pim_sock_fd, src, rpg->rpf_addr.u.prefix4, +			 buffer, buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) { +		if (PIM_DEBUG_PIM_TRACE) { +			zlog_debug( +				"%s: could not send PIM register message on interface %s", +				__PRETTY_FUNCTION__, ifp->name); +		} +		return; +	}  }  /* @@ -265,155 +259,160 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct   *      }   *  }   */ -int -pim_register_recv (struct interface *ifp, -		   struct in_addr dest_addr, -		   struct in_addr src_addr, -		   uint8_t *tlv_buf, int tlv_buf_size) +int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, +		      struct in_addr src_addr, uint8_t *tlv_buf, +		      int tlv_buf_size)  { -  int sentRegisterStop = 0; -  struct ip *ip_hdr; -  struct prefix_sg sg; -  uint32_t *bits; -  int i_am_rp = 0; -  struct pim_interface *pim_ifp = NULL; +	int sentRegisterStop = 0; +	struct ip *ip_hdr; +	struct prefix_sg sg; +	uint32_t *bits; +	int i_am_rp = 0; +	struct pim_interface *pim_ifp = NULL;  #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 -  ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); - -  if (!pim_rp_check_is_my_ip_address (ip_hdr->ip_dst, dest_addr)) { -    if (PIM_DEBUG_PIM_REG) { -      char dest[INET_ADDRSTRLEN]; - -      pim_inet4_dump ("<dst?>", dest_addr, dest, sizeof(dest)); -      zlog_debug ("%s: Received Register message for %s that I do not own", __func__, -		  dest); -    } -    return 0; -  } - -  pim_ifp = ifp->info; -  zassert(pim_ifp); -  ++pim_ifp->pim_ifstat_reg_recv; - -  /* -   * Please note this is not drawn to get the correct bit/data size -   * -   * The entirety of the REGISTER packet looks like this: -   * ------------------------------------------------------------- -   * | Ver  | Type | Reserved     |       Checksum               | -   * |-----------------------------------------------------------| -   * |B|N|     Reserved 2                                        | -   * |-----------------------------------------------------------| -   * | Encap  |                IP HDR                            | -   * | Mcast  |                                                  | -   * | Packet |--------------------------------------------------| -   * |        |               Mcast Data                         | -   * |        |                                                  | -   * ... -   * -   * tlv_buf when received from the caller points at the B bit -   * We need to know the inner source and dest -   */ -  bits = (uint32_t *)tlv_buf; - -  /* -   * tlv_buf points to the start of the |B|N|... Reserved -   * Line above.  So we need to add 4 bytes to get to the -   * start of the actual Encapsulated data. -   */ -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = ip_hdr->ip_src; -  sg.grp = ip_hdr->ip_dst; - -  i_am_rp = I_am_RP (sg.grp); - -  if (PIM_DEBUG_PIM_REG) -    { -      char src_str[INET_ADDRSTRLEN]; - -      pim_inet4_dump ("<src?>", src_addr, src_str, sizeof (src_str)); -      zlog_debug ("Received Register message(%s) from %s on %s, rp: %d", -                  pim_str_sg_dump (&sg), src_str, ifp->name, i_am_rp); -    } - -  if (i_am_rp && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) { -    sentRegisterStop = 0; - -    if (*bits & PIM_REGISTER_BORDER_BIT) { -      struct in_addr pimbr = pim_br_get_pmbr (&sg); -      if (PIM_DEBUG_PIM_PACKETS) -	zlog_debug("%s: Received Register message with Border bit set", __func__); - -      if (pimbr.s_addr == pim_br_unknown.s_addr) -	pim_br_set_pmbr(&sg, src_addr); -      else if (src_addr.s_addr != pimbr.s_addr) { -	pim_register_stop_send (ifp, &sg, dest_addr, src_addr); -	if (PIM_DEBUG_PIM_PACKETS) -	  zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", -	    __func__, "Sender"); -	/* Drop Packet Silently */ +	ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); + +	if (!pim_rp_check_is_my_ip_address(ip_hdr->ip_dst, dest_addr)) { +		if (PIM_DEBUG_PIM_REG) { +			char dest[INET_ADDRSTRLEN]; + +			pim_inet4_dump("<dst?>", dest_addr, dest, sizeof(dest)); +			zlog_debug( +				"%s: Received Register message for %s that I do not own", +				__func__, dest); +		} +		return 0; +	} + +	pim_ifp = ifp->info; +	zassert(pim_ifp); +	++pim_ifp->pim_ifstat_reg_recv; + +	/* +	 * Please note this is not drawn to get the correct bit/data size +	 * +	 * The entirety of the REGISTER packet looks like this: +	 * ------------------------------------------------------------- +	 * | Ver  | Type | Reserved     |       Checksum               | +	 * |-----------------------------------------------------------| +	 * |B|N|     Reserved 2                                        | +	 * |-----------------------------------------------------------| +	 * | Encap  |                IP HDR                            | +	 * | Mcast  |                                                  | +	 * | Packet |--------------------------------------------------| +	 * |        |               Mcast Data                         | +	 * |        |                                                  | +	 * ... +	 * +	 * tlv_buf when received from the caller points at the B bit +	 * We need to know the inner source and dest +	 */ +	bits = (uint32_t *)tlv_buf; + +	/* +	 * tlv_buf points to the start of the |B|N|... Reserved +	 * Line above.  So we need to add 4 bytes to get to the +	 * start of the actual Encapsulated data. +	 */ +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = ip_hdr->ip_src; +	sg.grp = ip_hdr->ip_dst; + +	i_am_rp = I_am_RP(sg.grp); + +	if (PIM_DEBUG_PIM_REG) { +		char src_str[INET_ADDRSTRLEN]; + +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_debug( +			"Received Register message(%s) from %s on %s, rp: %d", +			pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp); +	} + +	if (i_am_rp && (dest_addr.s_addr +			== ((RP(sg.grp))->rpf_addr.u.prefix4.s_addr))) { +		sentRegisterStop = 0; + +		if (*bits & PIM_REGISTER_BORDER_BIT) { +			struct in_addr pimbr = pim_br_get_pmbr(&sg); +			if (PIM_DEBUG_PIM_PACKETS) +				zlog_debug( +					"%s: Received Register message with Border bit set", +					__func__); + +			if (pimbr.s_addr == pim_br_unknown.s_addr) +				pim_br_set_pmbr(&sg, src_addr); +			else if (src_addr.s_addr != pimbr.s_addr) { +				pim_register_stop_send(ifp, &sg, dest_addr, +						       src_addr); +				if (PIM_DEBUG_PIM_PACKETS) +					zlog_debug( +						"%s: Sending register-Stop to %s and dropping mr. packet", +						__func__, "Sender"); +				/* Drop Packet Silently */ +				return 0; +			} +		} + +		struct pim_upstream *upstream = pim_upstream_find(&sg); +		/* +		 * If we don't have a place to send ignore the packet +		 */ +		if (!upstream) { +			upstream = pim_upstream_add( +				&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, +				__PRETTY_FUNCTION__); +			if (!upstream) { +				zlog_warn("Failure to create upstream state"); +				return 1; +			} + +			upstream->upstream_register = src_addr; +		} + +		if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) +		    || ((SwitchToSptDesired(&sg)) +			&& pim_upstream_inherited_olist(upstream) == 0)) { +			// pim_scan_individual_oil (upstream->channel_oil); +			pim_register_stop_send(ifp, &sg, dest_addr, src_addr); +			sentRegisterStop = 1; +		} else { +			if (PIM_DEBUG_PIM_REG) +				zlog_debug("(%s) sptbit: %d", upstream->sg_str, +					   upstream->sptbit); +		} +		if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) +		    || (SwitchToSptDesired(&sg))) { +			if (sentRegisterStop) { +				pim_upstream_keep_alive_timer_start( +					upstream, qpim_rp_keep_alive_time); +			} else { +				pim_upstream_keep_alive_timer_start( +					upstream, qpim_keep_alive_time); +			} +		} + +		if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) +		    && !(*bits & PIM_REGISTER_NR_BIT)) { +			// decapsulate and forward the iner packet to +			// inherited_olist(S,G,rpt) +			// This is taken care of by the kernel for us +		} +		pim_upstream_msdp_reg_timer_start(upstream); +	} else { +		if (PIM_DEBUG_PIM_REG) { +			if (!i_am_rp) +				zlog_debug( +					"Received Register packet for %s, Rejecting packet because I am not the RP configured for group", +					pim_str_sg_dump(&sg)); +			else +				zlog_debug( +					"Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", +					pim_str_sg_dump(&sg)); +		} +		pim_register_stop_send(ifp, &sg, dest_addr, src_addr); +	} +  	return 0; -      } -    } - -    struct pim_upstream *upstream = pim_upstream_find (&sg); -    /* -     * If we don't have a place to send ignore the packet -     */ -    if (!upstream) -      { -        upstream = pim_upstream_add (&sg, ifp, -                                     PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, -                                     __PRETTY_FUNCTION__); -        if (!upstream) -          { -            zlog_warn ("Failure to create upstream state"); -            return 1; -          } - -        upstream->upstream_register = src_addr; -      } - -    if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || -	((SwitchToSptDesired(&sg)) && -	 pim_upstream_inherited_olist (upstream) == 0)) { -      //pim_scan_individual_oil (upstream->channel_oil); -      pim_register_stop_send (ifp, &sg, dest_addr, src_addr); -      sentRegisterStop = 1; -    } else { -      if (PIM_DEBUG_PIM_REG) -         zlog_debug ("(%s) sptbit: %d", upstream->sg_str, upstream->sptbit); -    } -    if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || -	(SwitchToSptDesired(&sg))) { -      if (sentRegisterStop) { -	pim_upstream_keep_alive_timer_start (upstream, qpim_rp_keep_alive_time); -      } else { -	pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time); -      } -    } - -    if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && -	!(*bits & PIM_REGISTER_NR_BIT)) -      { -	//decapsulate and forward the iner packet to -	//inherited_olist(S,G,rpt) -	// This is taken care of by the kernel for us -      } -     pim_upstream_msdp_reg_timer_start(upstream); -  } else { -    if (PIM_DEBUG_PIM_REG) -      { -	if (!i_am_rp) -	  zlog_debug ("Received Register packet for %s, Rejecting packet because I am not the RP configured for group", -		      pim_str_sg_dump (&sg)); -	else -	  zlog_debug ("Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", -		      pim_str_sg_dump (&sg)); -      } -    pim_register_stop_send (ifp, &sg, dest_addr, src_addr); -  } - -  return 0;  } diff --git a/pimd/pim_register.h b/pimd/pim_register.h index adb703c611..ad3deb2b24 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -30,15 +30,17 @@  #define PIM_MSG_REGISTER_LEN   (8)  #define PIM_MSG_REGISTER_STOP_LEN (4) -int pim_register_stop_recv (uint8_t *buf, int buf_size); - -int pim_register_recv (struct interface *ifp, -		       struct in_addr dest_addr, -		       struct in_addr src_addr, -		       uint8_t *tlv_buf, int tlv_buf_size); - -void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up); -void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator); -void pim_register_join (struct pim_upstream *up); +int pim_register_stop_recv(uint8_t *buf, int buf_size); + +int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, +		      struct in_addr src_addr, uint8_t *tlv_buf, +		      int tlv_buf_size); + +void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, +		       struct pim_rpf *rpg, int null_register, +		       struct pim_upstream *up); +void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg, +			    struct in_addr src, struct in_addr originator); +void pim_register_join(struct pim_upstream *up);  #endif diff --git a/pimd/pim_routemap.c b/pimd/pim_routemap.c index 20c716c3e9..6d06229b98 100644 --- a/pimd/pim_routemap.c +++ b/pimd/pim_routemap.c @@ -27,55 +27,49 @@  #include "pimd.h" -static void -pim_route_map_mark_update (const char *rmap_name) +static void pim_route_map_mark_update(const char *rmap_name)  { -  // placeholder -  return; +	// placeholder +	return;  } -static void -pim_route_map_add (const char *rmap_name) +static void pim_route_map_add(const char *rmap_name)  { -  if (route_map_mark_updated(rmap_name, 0) == 0) -    pim_route_map_mark_update(rmap_name); +	if (route_map_mark_updated(rmap_name, 0) == 0) +		pim_route_map_mark_update(rmap_name); -  route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +	route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);  } -static void -pim_route_map_delete (const char *rmap_name) +static void pim_route_map_delete(const char *rmap_name)  { -  if (route_map_mark_updated(rmap_name, 1) == 0) -    pim_route_map_mark_update(rmap_name); +	if (route_map_mark_updated(rmap_name, 1) == 0) +		pim_route_map_mark_update(rmap_name); -  route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); +	route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);  } -static void -pim_route_map_event (route_map_event_t event, const char *rmap_name) +static void pim_route_map_event(route_map_event_t event, const char *rmap_name)  { -  if (route_map_mark_updated(rmap_name, 0) == 0) -    pim_route_map_mark_update(rmap_name); +	if (route_map_mark_updated(rmap_name, 0) == 0) +		pim_route_map_mark_update(rmap_name); -  route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +	route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);  } -void -pim_route_map_init (void) +void pim_route_map_init(void)  { -  route_map_init (); +	route_map_init(); -  route_map_add_hook (pim_route_map_add); -  route_map_delete_hook (pim_route_map_delete); -  route_map_event_hook (pim_route_map_event); +	route_map_add_hook(pim_route_map_add); +	route_map_delete_hook(pim_route_map_delete); +	route_map_event_hook(pim_route_map_event);  } -void -pim_route_map_terminate (void) +void pim_route_map_terminate(void)  { -  route_map_add_hook (NULL); -  route_map_delete_hook (NULL); -  route_map_event_hook (NULL); -  route_map_finish(); +	route_map_add_hook(NULL); +	route_map_delete_hook(NULL); +	route_map_event_hook(NULL); +	route_map_finish();  } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 28300dbdff..2fe0143a87 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -48,158 +48,147 @@  static struct list *qpim_rp_list = NULL;  static struct rp_info *tail = NULL; -static void -pim_rp_info_free (struct rp_info *rp_info) +static void pim_rp_info_free(struct rp_info *rp_info)  { -  XFREE (MTYPE_PIM_RP, rp_info); +	XFREE(MTYPE_PIM_RP, rp_info);  } -int -pim_rp_list_cmp (void *v1, void *v2) +int pim_rp_list_cmp(void *v1, void *v2)  { -  struct rp_info *rp1 = (struct rp_info *)v1; -  struct rp_info *rp2 = (struct rp_info *)v2; - -  /* -   * Sort by RP IP address -   */ -  if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr) -    return -1; - -  if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr) -    return 1; - -  /* -   * Sort by group IP address -   */ -  if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) -    return -1; - -  if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) -    return 1; - -  return 0; +	struct rp_info *rp1 = (struct rp_info *)v1; +	struct rp_info *rp2 = (struct rp_info *)v2; + +	/* +	 * Sort by RP IP address +	 */ +	if (rp1->rp.rpf_addr.u.prefix4.s_addr +	    < rp2->rp.rpf_addr.u.prefix4.s_addr) +		return -1; + +	if (rp1->rp.rpf_addr.u.prefix4.s_addr +	    > rp2->rp.rpf_addr.u.prefix4.s_addr) +		return 1; + +	/* +	 * Sort by group IP address +	 */ +	if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) +		return -1; + +	if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) +		return 1; + +	return 0;  } -void -pim_rp_init (void) +void pim_rp_init(void)  { -  struct rp_info *rp_info; +	struct rp_info *rp_info; -  qpim_rp_list = list_new (); -  qpim_rp_list->del = (void (*)(void *))pim_rp_info_free; -  qpim_rp_list->cmp = pim_rp_list_cmp; +	qpim_rp_list = list_new(); +	qpim_rp_list->del = (void (*)(void *))pim_rp_info_free; +	qpim_rp_list->cmp = pim_rp_list_cmp; -  rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); +	rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); -  if (!rp_info) -    return; +	if (!rp_info) +		return; -  str2prefix ("224.0.0.0/4", &rp_info->group); -  rp_info->group.family = AF_INET; -  rp_info->rp.rpf_addr.family = AF_INET; -  rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; -  rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; -  tail = rp_info; +	str2prefix("224.0.0.0/4", &rp_info->group); +	rp_info->group.family = AF_INET; +	rp_info->rp.rpf_addr.family = AF_INET; +	rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; +	rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; +	tail = rp_info; -  listnode_add (qpim_rp_list, rp_info); +	listnode_add(qpim_rp_list, rp_info);  } -void -pim_rp_free (void) +void pim_rp_free(void)  { -  if (qpim_rp_list) -    list_delete (qpim_rp_list); -  qpim_rp_list = NULL; +	if (qpim_rp_list) +		list_delete(qpim_rp_list); +	qpim_rp_list = NULL;  }  /*   * Given an RP's prefix-list, return the RP's rp_info for that prefix-list   */ -static struct rp_info * -pim_rp_find_prefix_list (struct in_addr rp, const char *plist) +static struct rp_info *pim_rp_find_prefix_list(struct in_addr rp, +					       const char *plist)  { -  struct listnode *node; -  struct rp_info *rp_info; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && -          rp_info->plist && strcmp(rp_info->plist, plist) == 0) -        { -          return rp_info; -        } -    } - -  return NULL; +	struct listnode *node; +	struct rp_info *rp_info; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr +		    && rp_info->plist && strcmp(rp_info->plist, plist) == 0) { +			return rp_info; +		} +	} + +	return NULL;  }  /*   * Return true if plist is used by any rp_info   */ -static int -pim_rp_prefix_list_used (const char *plist) +static int pim_rp_prefix_list_used(const char *plist)  { -  struct listnode *node; -  struct rp_info *rp_info; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) -        { -          return 1; -        } -    } - -  return 0; +	struct listnode *node; +	struct rp_info *rp_info; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) { +			return 1; +		} +	} + +	return 0;  }  /* - * Given an RP's address, return the RP's rp_info that is an exact match for 'group' + * Given an RP's address, return the RP's rp_info that is an exact match for + * 'group'   */ -static struct rp_info * -pim_rp_find_exact (struct in_addr rp, struct prefix *group) +static struct rp_info *pim_rp_find_exact(struct in_addr rp, +					 struct prefix *group)  { -  struct listnode *node; -  struct rp_info *rp_info; +	struct listnode *node; +	struct rp_info *rp_info; -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && -	  prefix_same (&rp_info->group, group)) -       return rp_info; -    } +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr +		    && prefix_same(&rp_info->group, group)) +			return rp_info; +	} -  return NULL; +	return NULL;  }  /*   * Given a group, return the rp_info for that group   */ -static struct rp_info * -pim_rp_find_match_group (struct prefix *group) +static struct rp_info *pim_rp_find_match_group(struct prefix *group)  { -  struct listnode *node; -  struct rp_info *rp_info; -  struct prefix_list *plist; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (rp_info->plist) -        { -          plist = prefix_list_lookup (AFI_IP, rp_info->plist); - -          if (plist && prefix_list_apply (plist, group) == PREFIX_PERMIT) -            return rp_info; -        } -      else -        { -          if (prefix_match (&rp_info->group, group)) -            return rp_info; -        } -    } - -  return NULL; +	struct listnode *node; +	struct rp_info *rp_info; +	struct prefix_list *plist; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (rp_info->plist) { +			plist = prefix_list_lookup(AFI_IP, rp_info->plist); + +			if (plist +			    && prefix_list_apply(plist, group) == PREFIX_PERMIT) +				return rp_info; +		} else { +			if (prefix_match(&rp_info->group, group)) +				return rp_info; +		} +	} + +	return NULL;  }  /* @@ -209,480 +198,475 @@ pim_rp_find_match_group (struct prefix *group)   *   * This is a placeholder function for now.   */ -static void -pim_rp_refresh_group_to_rp_mapping() +static void pim_rp_refresh_group_to_rp_mapping()  { -  pim_msdp_i_am_rp_changed(); +	pim_msdp_i_am_rp_changed();  } -void -pim_rp_prefix_list_update (struct prefix_list *plist) +void pim_rp_prefix_list_update(struct prefix_list *plist)  { -  struct listnode *node; -  struct rp_info *rp_info; -  int refresh_needed = 0; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (rp_info->plist && strcmp(rp_info->plist, prefix_list_name (plist)) == 0) -        { -          refresh_needed = 1; -          break; -        } -    } - -  if (refresh_needed) -    pim_rp_refresh_group_to_rp_mapping(); +	struct listnode *node; +	struct rp_info *rp_info; +	int refresh_needed = 0; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (rp_info->plist +		    && strcmp(rp_info->plist, prefix_list_name(plist)) == 0) { +			refresh_needed = 1; +			break; +		} +	} + +	if (refresh_needed) +		pim_rp_refresh_group_to_rp_mapping();  } -static int -pim_rp_check_interface_addrs(struct rp_info *rp_info, -                             struct pim_interface *pim_ifp) +static int pim_rp_check_interface_addrs(struct rp_info *rp_info, +					struct pim_interface *pim_ifp)  { -  struct listnode *node; -  struct pim_secondary_addr *sec_addr; +	struct listnode *node; +	struct pim_secondary_addr *sec_addr; -  if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) -    return 1; +	if (pim_ifp->primary_address.s_addr +	    == rp_info->rp.rpf_addr.u.prefix4.s_addr) +		return 1; -  if (!pim_ifp->sec_addr_list) { -    return 0; -  } +	if (!pim_ifp->sec_addr_list) { +		return 0; +	} -  for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { -    if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { -      return 1; -    } -  } +	for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { +		if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { +			return 1; +		} +	} -  return 0; +	return 0;  } -static void -pim_rp_check_interfaces (struct rp_info *rp_info) +static void pim_rp_check_interfaces(struct rp_info *rp_info)  { -  struct listnode *node; -  struct interface *ifp; +	struct listnode *node; +	struct interface *ifp; -  rp_info->i_am_rp = 0; -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) -    { -      struct pim_interface *pim_ifp = ifp->info; +	rp_info->i_am_rp = 0; +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		struct pim_interface *pim_ifp = ifp->info; -      if (!pim_ifp) -        continue; +		if (!pim_ifp) +			continue; -      if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { -        rp_info->i_am_rp = 1; -      } -    } +		if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { +			rp_info->i_am_rp = 1; +		} +	}  } -int -pim_rp_new (const char *rp, const char *group_range, const char *plist) +int pim_rp_new(const char *rp, const char *group_range, const char *plist)  { -  int result = 0; -  struct rp_info *rp_info; -  struct rp_info *rp_all; -  struct prefix group_all; -  struct listnode *node, *nnode; -  struct rp_info *tmp_rp_info; -  char buffer[BUFSIZ]; -  struct prefix nht_p; -  struct pim_nexthop_cache pnc; - -  rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); -  if (!rp_info) -    return PIM_MALLOC_FAIL; - -  if (group_range == NULL) -    result = str2prefix ("224.0.0.0/4", &rp_info->group); -  else -    result = str2prefix (group_range, &rp_info->group); - -  if (!result) -    { -      XFREE (MTYPE_PIM_RP, rp_info); -      return PIM_GROUP_BAD_ADDRESS; -    } - -  rp_info->rp.rpf_addr.family = AF_INET; -  rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; -  result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix4); - -  if (result <= 0) -    { -      XFREE (MTYPE_PIM_RP, rp_info); -      return PIM_RP_BAD_ADDRESS; -    } - -  if (plist) -    { -      /* -       * Return if the prefix-list is already configured for this RP -       */ -      if (pim_rp_find_prefix_list (rp_info->rp.rpf_addr.u.prefix4, plist)) -        { -          XFREE (MTYPE_PIM_RP, rp_info); -          return PIM_SUCCESS; -        } - -      /* -       * Barf if the prefix-list is already configured for an RP -       */ -      if (pim_rp_prefix_list_used (plist)) -        { -          XFREE (MTYPE_PIM_RP, rp_info); -          return PIM_RP_PFXLIST_IN_USE; -        } - -      /* -       * Free any existing rp_info entries for this RP -       */ -      for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) -        { -          if (rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) -            { -              if (tmp_rp_info->plist) -                pim_rp_del (rp, NULL, tmp_rp_info->plist); -              else -                pim_rp_del (rp, prefix2str(&tmp_rp_info->group, buffer, BUFSIZ), NULL); -            } -        } - -      rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); -    } -  else -    { -      str2prefix ("224.0.0.0/4", &group_all); -      rp_all = pim_rp_find_match_group(&group_all); - -      /* -       * Barf if group is a non-multicast subnet -       */ -      if (! prefix_match (&rp_all->group, &rp_info->group)) -        { -          XFREE (MTYPE_PIM_RP, rp_info); -          return PIM_GROUP_BAD_ADDRESS; -        } - -      /* -       * Remove any prefix-list rp_info entries for this RP -       */ -      for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) -        { -          if (tmp_rp_info->plist && -              rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) -            { -              pim_rp_del (rp, NULL, tmp_rp_info->plist); -            } -        } - -      /* -       * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE -       */ -      if (prefix_same (&rp_all->group, &rp_info->group) && -          pim_rpf_addr_is_inaddr_none (&rp_all->rp)) -        { -          rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; -          XFREE (MTYPE_PIM_RP, rp_info); - -          /* Register addr with Zebra NHT */ -          nht_p.family = AF_INET; -          nht_p.prefixlen = IPV4_MAX_BITLEN; -          nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4;      //RP address -          if (PIM_DEBUG_PIM_TRACE) -            { -              char buf[PREFIX2STR_BUFFER]; -              char buf1[PREFIX2STR_BUFFER]; -              prefix2str (&nht_p, buf, sizeof (buf)); -              prefix2str (&rp_all->group, buf1, sizeof (buf1)); -              zlog_debug ("%s: NHT Register rp_all addr %s grp %s ", -                          __PRETTY_FUNCTION__, buf, buf1); -            } -          memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -          if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_all, &pnc)) == 1) -            { -              //Compute PIM RPF using Cached nexthop -              if ((pim_ecmp_nexthop_search (&pnc, &rp_all->rp.source_nexthop, -                                       &nht_p, &rp_all->group, 1)) != 0) -                return PIM_RP_NO_PATH; -            } -          else -            { -              if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0) -                return PIM_RP_NO_PATH; -            } -          pim_rp_check_interfaces (rp_all); -          pim_rp_refresh_group_to_rp_mapping (); -          return PIM_SUCCESS; -        } - -      /* -       * Return if the group is already configured for this RP -       */ -      if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) -        { -          XFREE (MTYPE_PIM_RP, rp_info); -          return PIM_SUCCESS; -        } - -      /* -       * Barf if this group is already covered by some other RP -       */ -      tmp_rp_info = pim_rp_find_match_group (&rp_info->group); - -      if (tmp_rp_info) -        { -          if (tmp_rp_info->plist) -            { -                XFREE (MTYPE_PIM_RP, rp_info); -                return PIM_GROUP_PFXLIST_OVERLAP; -            } -          else -            { -              /* -               * If the only RP that covers this group is an RP configured for -               * 224.0.0.0/4 that is fine, ignore that one.  For all others -               * though we must return PIM_GROUP_OVERLAP -               */ -              if (! prefix_same (&group_all, &tmp_rp_info->group)) -                { -                  XFREE (MTYPE_PIM_RP, rp_info); -                  return PIM_GROUP_OVERLAP; -                } -            } -        } -    } - -  listnode_add_sort (qpim_rp_list, rp_info); - -  /* Register addr with Zebra NHT */ -  nht_p.family = AF_INET; -  nht_p.prefixlen = IPV4_MAX_BITLEN; -  nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; -  if (PIM_DEBUG_PIM_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      char buf1[PREFIX2STR_BUFFER]; -      prefix2str (&nht_p, buf, sizeof (buf)); -      prefix2str (&rp_info->group, buf1, sizeof (buf1)); -      zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ", -                  __PRETTY_FUNCTION__, buf, buf1); -    } - -  memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -  if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) -    { -      //Compute PIM RPF using Cached nexthop -      if (pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, -                               &nht_p, &rp_info->group, 1) != 0) -        return PIM_RP_NO_PATH; -    } -  else -    { -      if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) -        return PIM_RP_NO_PATH; -    } - -  pim_rp_check_interfaces (rp_info); -  pim_rp_refresh_group_to_rp_mapping (); -  return PIM_SUCCESS; +	int result = 0; +	struct rp_info *rp_info; +	struct rp_info *rp_all; +	struct prefix group_all; +	struct listnode *node, *nnode; +	struct rp_info *tmp_rp_info; +	char buffer[BUFSIZ]; +	struct prefix nht_p; +	struct pim_nexthop_cache pnc; + +	rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); +	if (!rp_info) +		return PIM_MALLOC_FAIL; + +	if (group_range == NULL) +		result = str2prefix("224.0.0.0/4", &rp_info->group); +	else +		result = str2prefix(group_range, &rp_info->group); + +	if (!result) { +		XFREE(MTYPE_PIM_RP, rp_info); +		return PIM_GROUP_BAD_ADDRESS; +	} + +	rp_info->rp.rpf_addr.family = AF_INET; +	rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; +	result = inet_pton(rp_info->rp.rpf_addr.family, rp, +			   &rp_info->rp.rpf_addr.u.prefix4); + +	if (result <= 0) { +		XFREE(MTYPE_PIM_RP, rp_info); +		return PIM_RP_BAD_ADDRESS; +	} + +	if (plist) { +		/* +		 * Return if the prefix-list is already configured for this RP +		 */ +		if (pim_rp_find_prefix_list(rp_info->rp.rpf_addr.u.prefix4, +					    plist)) { +			XFREE(MTYPE_PIM_RP, rp_info); +			return PIM_SUCCESS; +		} + +		/* +		 * Barf if the prefix-list is already configured for an RP +		 */ +		if (pim_rp_prefix_list_used(plist)) { +			XFREE(MTYPE_PIM_RP, rp_info); +			return PIM_RP_PFXLIST_IN_USE; +		} + +		/* +		 * Free any existing rp_info entries for this RP +		 */ +		for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode, +				       tmp_rp_info)) { +			if (rp_info->rp.rpf_addr.u.prefix4.s_addr +			    == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) { +				if (tmp_rp_info->plist) +					pim_rp_del(rp, NULL, +						   tmp_rp_info->plist); +				else +					pim_rp_del( +						rp, +						prefix2str(&tmp_rp_info->group, +							   buffer, BUFSIZ), +						NULL); +			} +		} + +		rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); +	} else { +		str2prefix("224.0.0.0/4", &group_all); +		rp_all = pim_rp_find_match_group(&group_all); + +		/* +		 * Barf if group is a non-multicast subnet +		 */ +		if (!prefix_match(&rp_all->group, &rp_info->group)) { +			XFREE(MTYPE_PIM_RP, rp_info); +			return PIM_GROUP_BAD_ADDRESS; +		} + +		/* +		 * Remove any prefix-list rp_info entries for this RP +		 */ +		for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode, +				       tmp_rp_info)) { +			if (tmp_rp_info->plist +			    && rp_info->rp.rpf_addr.u.prefix4.s_addr +				       == tmp_rp_info->rp.rpf_addr.u.prefix4 +						  .s_addr) { +				pim_rp_del(rp, NULL, tmp_rp_info->plist); +			} +		} + +		/* +		 * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE +		 */ +		if (prefix_same(&rp_all->group, &rp_info->group) +		    && pim_rpf_addr_is_inaddr_none(&rp_all->rp)) { +			rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; +			XFREE(MTYPE_PIM_RP, rp_info); + +			/* Register addr with Zebra NHT */ +			nht_p.family = AF_INET; +			nht_p.prefixlen = IPV4_MAX_BITLEN; +			nht_p.u.prefix4 = +				rp_all->rp.rpf_addr.u.prefix4; // RP address +			if (PIM_DEBUG_PIM_TRACE) { +				char buf[PREFIX2STR_BUFFER]; +				char buf1[PREFIX2STR_BUFFER]; +				prefix2str(&nht_p, buf, sizeof(buf)); +				prefix2str(&rp_all->group, buf1, sizeof(buf1)); +				zlog_debug( +					"%s: NHT Register rp_all addr %s grp %s ", +					__PRETTY_FUNCTION__, buf, buf1); +			} +			memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +			if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_all, +						       &pnc)) +			    == 1) { +				// Compute PIM RPF using Cached nexthop +				if ((pim_ecmp_nexthop_search( +					    &pnc, &rp_all->rp.source_nexthop, +					    &nht_p, &rp_all->group, 1)) +				    != 0) +					return PIM_RP_NO_PATH; +			} else { +				if (pim_nexthop_lookup( +					    &rp_all->rp.source_nexthop, +					    rp_all->rp.rpf_addr.u.prefix4, 1) +				    != 0) +					return PIM_RP_NO_PATH; +			} +			pim_rp_check_interfaces(rp_all); +			pim_rp_refresh_group_to_rp_mapping(); +			return PIM_SUCCESS; +		} + +		/* +		 * Return if the group is already configured for this RP +		 */ +		if (pim_rp_find_exact(rp_info->rp.rpf_addr.u.prefix4, +				      &rp_info->group)) { +			XFREE(MTYPE_PIM_RP, rp_info); +			return PIM_SUCCESS; +		} + +		/* +		 * Barf if this group is already covered by some other RP +		 */ +		tmp_rp_info = pim_rp_find_match_group(&rp_info->group); + +		if (tmp_rp_info) { +			if (tmp_rp_info->plist) { +				XFREE(MTYPE_PIM_RP, rp_info); +				return PIM_GROUP_PFXLIST_OVERLAP; +			} else { +				/* +				 * If the only RP that covers this group is an +				 * RP configured for +				 * 224.0.0.0/4 that is fine, ignore that one. +				 * For all others +				 * though we must return PIM_GROUP_OVERLAP +				 */ +				if (!prefix_same(&group_all, +						 &tmp_rp_info->group)) { +					XFREE(MTYPE_PIM_RP, rp_info); +					return PIM_GROUP_OVERLAP; +				} +			} +		} +	} + +	listnode_add_sort(qpim_rp_list, rp_info); + +	/* Register addr with Zebra NHT */ +	nht_p.family = AF_INET; +	nht_p.prefixlen = IPV4_MAX_BITLEN; +	nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; +	if (PIM_DEBUG_PIM_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		char buf1[PREFIX2STR_BUFFER]; +		prefix2str(&nht_p, buf, sizeof(buf)); +		prefix2str(&rp_info->group, buf1, sizeof(buf1)); +		zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ", +			   __PRETTY_FUNCTION__, buf, buf1); +	} + +	memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +	if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) == 1) { +		// Compute PIM RPF using Cached nexthop +		if (pim_ecmp_nexthop_search(&pnc, &rp_info->rp.source_nexthop, +					    &nht_p, &rp_info->group, 1) +		    != 0) +			return PIM_RP_NO_PATH; +	} else { +		if (pim_nexthop_lookup(&rp_info->rp.source_nexthop, +				       rp_info->rp.rpf_addr.u.prefix4, 1) +		    != 0) +			return PIM_RP_NO_PATH; +	} + +	pim_rp_check_interfaces(rp_info); +	pim_rp_refresh_group_to_rp_mapping(); +	return PIM_SUCCESS;  } -int -pim_rp_del (const char *rp, const char *group_range, const char *plist) +int pim_rp_del(const char *rp, const char *group_range, const char *plist)  { -  struct prefix group; -  struct in_addr rp_addr; -  struct prefix g_all; -  struct rp_info *rp_info; -  struct rp_info *rp_all; -  int result; -  struct prefix nht_p; - -  if (group_range == NULL) -    result = str2prefix ("224.0.0.0/4", &group); -  else -    result = str2prefix (group_range, &group); - -  if (!result) -    return PIM_GROUP_BAD_ADDRESS; - -  result = inet_pton (AF_INET, rp, &rp_addr); -  if (result <= 0) -    return PIM_RP_BAD_ADDRESS; - -  if (plist) -    rp_info = pim_rp_find_prefix_list (rp_addr, plist); -  else -    rp_info = pim_rp_find_exact (rp_addr, &group); - -  if (!rp_info) -    return PIM_RP_NOT_FOUND; - -  if (rp_info->plist) -    { -      XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); -      rp_info->plist = NULL; -    } - -  /* Deregister addr with Zebra NHT */ -  nht_p.family = AF_INET; -  nht_p.prefixlen = IPV4_MAX_BITLEN; -  nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; -  if (PIM_DEBUG_PIM_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      prefix2str (&nht_p, buf, sizeof (buf)); -      zlog_debug ("%s: Deregister RP addr %s with Zebra ", __PRETTY_FUNCTION__, -                  buf); -    } -  pim_delete_tracked_nexthop (&nht_p, NULL, rp_info); - -  str2prefix ("224.0.0.0/4", &g_all); -  rp_all = pim_rp_find_match_group (&g_all); - -  if (rp_all == rp_info) -    { -      rp_all->rp.rpf_addr.family = AF_INET; -      rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; -      rp_all->i_am_rp = 0; -      return PIM_SUCCESS; -    } - -  listnode_delete (qpim_rp_list, rp_info); -  pim_rp_refresh_group_to_rp_mapping (); -  return PIM_SUCCESS; +	struct prefix group; +	struct in_addr rp_addr; +	struct prefix g_all; +	struct rp_info *rp_info; +	struct rp_info *rp_all; +	int result; +	struct prefix nht_p; + +	if (group_range == NULL) +		result = str2prefix("224.0.0.0/4", &group); +	else +		result = str2prefix(group_range, &group); + +	if (!result) +		return PIM_GROUP_BAD_ADDRESS; + +	result = inet_pton(AF_INET, rp, &rp_addr); +	if (result <= 0) +		return PIM_RP_BAD_ADDRESS; + +	if (plist) +		rp_info = pim_rp_find_prefix_list(rp_addr, plist); +	else +		rp_info = pim_rp_find_exact(rp_addr, &group); + +	if (!rp_info) +		return PIM_RP_NOT_FOUND; + +	if (rp_info->plist) { +		XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); +		rp_info->plist = NULL; +	} + +	/* Deregister addr with Zebra NHT */ +	nht_p.family = AF_INET; +	nht_p.prefixlen = IPV4_MAX_BITLEN; +	nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; +	if (PIM_DEBUG_PIM_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		prefix2str(&nht_p, buf, sizeof(buf)); +		zlog_debug("%s: Deregister RP addr %s with Zebra ", +			   __PRETTY_FUNCTION__, buf); +	} +	pim_delete_tracked_nexthop(&nht_p, NULL, rp_info); + +	str2prefix("224.0.0.0/4", &g_all); +	rp_all = pim_rp_find_match_group(&g_all); + +	if (rp_all == rp_info) { +		rp_all->rp.rpf_addr.family = AF_INET; +		rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; +		rp_all->i_am_rp = 0; +		return PIM_SUCCESS; +	} + +	listnode_delete(qpim_rp_list, rp_info); +	pim_rp_refresh_group_to_rp_mapping(); +	return PIM_SUCCESS;  } -int -pim_rp_setup (void) +int pim_rp_setup(void)  { -  struct listnode *node; -  struct rp_info *rp_info; -  int ret = 0; -  struct prefix nht_p; -  struct pim_nexthop_cache pnc; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) -        continue; - -      nht_p.family = AF_INET; -      nht_p.prefixlen = IPV4_MAX_BITLEN; -      nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; -      memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -      if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) -        { -          //Compute PIM RPF using Cached nexthop -          if ((pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, -                                   &nht_p, &rp_info->group, 1)) != 0) -            ret++; -        } -      else -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char buf[PREFIX2STR_BUFFER]; -              prefix2str (&nht_p, buf, sizeof (buf)); -              zlog_debug ("%s: NHT Local Nexthop not found for RP %s ", -                          __PRETTY_FUNCTION__, buf); -            } -          if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) -            { -              if (PIM_DEBUG_PIM_TRACE) -                zlog_debug ("Unable to lookup nexthop for rp specified"); -              ret++; -            } -        } -    } - -  if (ret) -    return 0; - -  return 1; +	struct listnode *node; +	struct rp_info *rp_info; +	int ret = 0; +	struct prefix nht_p; +	struct pim_nexthop_cache pnc; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) +			continue; + +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; +		memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +		if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) +		    == 1) { +			// Compute PIM RPF using Cached nexthop +			if ((pim_ecmp_nexthop_search( +				    &pnc, &rp_info->rp.source_nexthop, &nht_p, +				    &rp_info->group, 1)) +			    != 0) +				ret++; +		} else { +			if (PIM_DEBUG_ZEBRA) { +				char buf[PREFIX2STR_BUFFER]; +				prefix2str(&nht_p, buf, sizeof(buf)); +				zlog_debug( +					"%s: NHT Local Nexthop not found for RP %s ", +					__PRETTY_FUNCTION__, buf); +			} +			if (pim_nexthop_lookup(&rp_info->rp.source_nexthop, +					       rp_info->rp.rpf_addr.u.prefix4, +					       1) +			    != 0) { +				if (PIM_DEBUG_PIM_TRACE) +					zlog_debug( +						"Unable to lookup nexthop for rp specified"); +				ret++; +			} +		} +	} + +	if (ret) +		return 0; + +	return 1;  }  /*   * Checks to see if we should elect ourself the actual RP when new if   * addresses are added against an interface.   */ -void -pim_rp_check_on_if_add(struct pim_interface *pim_ifp) +void pim_rp_check_on_if_add(struct pim_interface *pim_ifp)  { -  struct listnode *node; -  struct rp_info *rp_info; -  bool i_am_rp_changed = false; - -  if (qpim_rp_list == NULL) -    return; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { -    if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) -      continue; - -    /* if i_am_rp is already set nothing to be done (adding new addresses -     * is not going to make a difference). */ -    if (rp_info->i_am_rp) { -      continue; -    } - -    if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { -      i_am_rp_changed = true; -      rp_info->i_am_rp = 1; -      if (PIM_DEBUG_ZEBRA) { -        char rp[PREFIX_STRLEN]; -        pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp, sizeof(rp)); -        zlog_debug("%s: %s: i am rp", __func__, rp); -      } -    } -  } - -  if (i_am_rp_changed) { -    pim_msdp_i_am_rp_changed(); -  } +	struct listnode *node; +	struct rp_info *rp_info; +	bool i_am_rp_changed = false; + +	if (qpim_rp_list == NULL) +		return; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) +			continue; + +		/* if i_am_rp is already set nothing to be done (adding new +		 * addresses +		 * is not going to make a difference). */ +		if (rp_info->i_am_rp) { +			continue; +		} + +		if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { +			i_am_rp_changed = true; +			rp_info->i_am_rp = 1; +			if (PIM_DEBUG_ZEBRA) { +				char rp[PREFIX_STRLEN]; +				pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, +					      rp, sizeof(rp)); +				zlog_debug("%s: %s: i am rp", __func__, rp); +			} +		} +	} + +	if (i_am_rp_changed) { +		pim_msdp_i_am_rp_changed(); +	}  }  /* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses   * are removed. Removing numbers is an uncommon event in an active network   * so I have made no attempt to optimize it. */ -void -pim_i_am_rp_re_evaluate(void) +void pim_i_am_rp_re_evaluate(void)  { -  struct listnode *node; -  struct rp_info *rp_info; -  bool i_am_rp_changed = false; -  int old_i_am_rp; - -  if (qpim_rp_list == NULL) -    return; - -  for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { -    if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) -      continue; - -    old_i_am_rp = rp_info->i_am_rp; -    pim_rp_check_interfaces(rp_info); - -    if (old_i_am_rp != rp_info->i_am_rp) { -      i_am_rp_changed = true; -      if (PIM_DEBUG_ZEBRA) { -        char rp[PREFIX_STRLEN]; -        pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, rp, sizeof(rp)); -        if (rp_info->i_am_rp) { -          zlog_debug("%s: %s: i am rp", __func__, rp); -        } else { -          zlog_debug("%s: %s: i am no longer rp", __func__, rp); -        } -      } -    } -  } - -  if (i_am_rp_changed) { -    pim_msdp_i_am_rp_changed(); -  } +	struct listnode *node; +	struct rp_info *rp_info; +	bool i_am_rp_changed = false; +	int old_i_am_rp; + +	if (qpim_rp_list == NULL) +		return; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) +			continue; + +		old_i_am_rp = rp_info->i_am_rp; +		pim_rp_check_interfaces(rp_info); + +		if (old_i_am_rp != rp_info->i_am_rp) { +			i_am_rp_changed = true; +			if (PIM_DEBUG_ZEBRA) { +				char rp[PREFIX_STRLEN]; +				pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr, +					      rp, sizeof(rp)); +				if (rp_info->i_am_rp) { +					zlog_debug("%s: %s: i am rp", __func__, +						   rp); +				} else { +					zlog_debug("%s: %s: i am no longer rp", +						   __func__, rp); +				} +			} +		} +	} + +	if (i_am_rp_changed) { +		pim_msdp_i_am_rp_changed(); +	}  }  /* @@ -691,23 +675,22 @@ pim_i_am_rp_re_evaluate(void)   *   * Since we only have static RP, all groups are part of this RP   */ -int -pim_rp_i_am_rp (struct in_addr group) +int pim_rp_i_am_rp(struct in_addr group)  { -  struct prefix g; -  struct rp_info *rp_info; +	struct prefix g; +	struct rp_info *rp_info; -  memset (&g, 0, sizeof (g)); -  g.family = AF_INET; -  g.prefixlen = 32; -  g.u.prefix4 = group; +	memset(&g, 0, sizeof(g)); +	g.family = AF_INET; +	g.prefixlen = 32; +	g.u.prefix4 = group; -  rp_info = pim_rp_find_match_group (&g); +	rp_info = pim_rp_find_match_group(&g); -  if (rp_info) -    return rp_info->i_am_rp; +	if (rp_info) +		return rp_info->i_am_rp; -  return 0; +	return 0;  }  /* @@ -715,62 +698,60 @@ pim_rp_i_am_rp (struct in_addr group)   *   * Return the RP that the Group belongs too.   */ -struct pim_rpf * -pim_rp_g (struct in_addr group) +struct pim_rpf *pim_rp_g(struct in_addr group)  { -  struct prefix g; -  struct rp_info *rp_info; - -  memset (&g, 0, sizeof (g)); -  g.family = AF_INET; -  g.prefixlen = 32; -  g.u.prefix4 = group; - -  rp_info = pim_rp_find_match_group (&g); - -  if (rp_info) -    { -      struct prefix nht_p; -      struct pim_nexthop_cache pnc; -      /* Register addr with Zebra NHT */ -      nht_p.family = AF_INET; -      nht_p.prefixlen = IPV4_MAX_BITLEN; -      nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; -      if (PIM_DEBUG_PIM_TRACE) -        { -          char buf[PREFIX2STR_BUFFER]; -          char buf1[PREFIX2STR_BUFFER]; -          prefix2str (&nht_p, buf, sizeof (buf)); -          prefix2str (&rp_info->group, buf1, sizeof (buf1)); -          zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra", -                      __PRETTY_FUNCTION__, buf, buf1); -        } -      memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -      if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) -        { -          //Compute PIM RPF using Cached nexthop -          pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, -                                   &nht_p, &rp_info->group, 1); -        } -      else -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char buf[PREFIX2STR_BUFFER]; -              char buf1[PREFIX2STR_BUFFER]; -              prefix2str (&nht_p, buf, sizeof (buf)); -              prefix2str (&g, buf1, sizeof (buf1)); -              zlog_debug ("%s: Nexthop cache not found for RP %s grp %s register with Zebra", -                          __PRETTY_FUNCTION__, buf, buf1); -            } -          pim_rpf_set_refresh_time (); -          pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1); -        } -      return (&rp_info->rp); -    } - -  // About to Go Down -  return NULL; +	struct prefix g; +	struct rp_info *rp_info; + +	memset(&g, 0, sizeof(g)); +	g.family = AF_INET; +	g.prefixlen = 32; +	g.u.prefix4 = group; + +	rp_info = pim_rp_find_match_group(&g); + +	if (rp_info) { +		struct prefix nht_p; +		struct pim_nexthop_cache pnc; +		/* Register addr with Zebra NHT */ +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; +		if (PIM_DEBUG_PIM_TRACE) { +			char buf[PREFIX2STR_BUFFER]; +			char buf1[PREFIX2STR_BUFFER]; +			prefix2str(&nht_p, buf, sizeof(buf)); +			prefix2str(&rp_info->group, buf1, sizeof(buf1)); +			zlog_debug( +				"%s: NHT Register RP addr %s grp %s with Zebra", +				__PRETTY_FUNCTION__, buf, buf1); +		} +		memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +		if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) +		    == 1) { +			// Compute PIM RPF using Cached nexthop +			pim_ecmp_nexthop_search(&pnc, +						&rp_info->rp.source_nexthop, +						&nht_p, &rp_info->group, 1); +		} else { +			if (PIM_DEBUG_ZEBRA) { +				char buf[PREFIX2STR_BUFFER]; +				char buf1[PREFIX2STR_BUFFER]; +				prefix2str(&nht_p, buf, sizeof(buf)); +				prefix2str(&g, buf1, sizeof(buf1)); +				zlog_debug( +					"%s: Nexthop cache not found for RP %s grp %s register with Zebra", +					__PRETTY_FUNCTION__, buf, buf1); +			} +			pim_rpf_set_refresh_time(); +			pim_nexthop_lookup(&rp_info->rp.source_nexthop, +					   rp_info->rp.rpf_addr.u.prefix4, 1); +		} +		return (&rp_info->rp); +	} + +	// About to Go Down +	return NULL;  }  /* @@ -781,222 +762,253 @@ pim_rp_g (struct in_addr group)   * then return failure.   *   */ -int -pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group) +int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source, +			     struct in_addr group)  { -  struct rp_info *rp_info; -  struct prefix g; +	struct rp_info *rp_info; +	struct prefix g; -  memset (&g, 0, sizeof (g)); -  g.family = AF_INET; -  g.prefixlen = 32; -  g.u.prefix4 = group; +	memset(&g, 0, sizeof(g)); +	g.family = AF_INET; +	g.prefixlen = 32; +	g.u.prefix4 = group; -  rp_info = pim_rp_find_match_group (&g); +	rp_info = pim_rp_find_match_group(&g); -  if ((pim_rpf_addr_is_inaddr_none (&rp_info->rp)) && (source.s_addr == INADDR_ANY)) -    { -      if (PIM_DEBUG_PIM_TRACE) -	zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); -      return 0; -    } +	if ((pim_rpf_addr_is_inaddr_none(&rp_info->rp)) +	    && (source.s_addr == INADDR_ANY)) { +		if (PIM_DEBUG_PIM_TRACE) +			zlog_debug("%s: Received a (*,G) with no RP configured", +				   __PRETTY_FUNCTION__); +		return 0; +	} -  *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4 : source; +	*up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4 +					    : source; -  return 1; +	return 1;  } -int -pim_rp_config_write (struct vty *vty) +int pim_rp_config_write(struct vty *vty)  { -  struct listnode *node; -  struct rp_info *rp_info; -  char rp_buffer[32]; -  char group_buffer[32]; -  int count = 0; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) -        continue; - -      if (rp_info->plist) -        vty_out (vty, "ip pim rp %s prefix-list %s\n", -                inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), -                rp_info->plist); -      else -        vty_out (vty, "ip pim rp %s %s\n", -                inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), -                prefix2str(&rp_info->group, group_buffer, 32)); -      count++; -    } - -  return count; +	struct listnode *node; +	struct rp_info *rp_info; +	char rp_buffer[32]; +	char group_buffer[32]; +	int count = 0; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) +			continue; + +		if (rp_info->plist) +			vty_out(vty, "ip pim rp %s prefix-list %s\n", +				inet_ntop(AF_INET, +					  &rp_info->rp.rpf_addr.u.prefix4, +					  rp_buffer, 32), +				rp_info->plist); +		else +			vty_out(vty, "ip pim rp %s %s\n", +				inet_ntop(AF_INET, +					  &rp_info->rp.rpf_addr.u.prefix4, +					  rp_buffer, 32), +				prefix2str(&rp_info->group, group_buffer, 32)); +		count++; +	} + +	return count;  } -int -pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) +int pim_rp_check_is_my_ip_address(struct in_addr group, +				  struct in_addr dest_addr)  { -  struct rp_info *rp_info; -  struct prefix g; - -  memset (&g, 0, sizeof (g)); -  g.family = AF_INET; -  g.prefixlen = 32; -  g.u.prefix4 = group; - -  rp_info = pim_rp_find_match_group (&g); -  /* -   * See if we can short-cut some? -   * This might not make sense if we ever leave a static RP -   * type of configuration. -   * Note - Premature optimization might bite our patooeys' here. -   */ -  if (I_am_RP(group)) -    { -     if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) -       return 1; -    } - -  if (if_lookup_exact_address (&dest_addr, AF_INET, VRF_DEFAULT)) -    return 1; - -  return 0; +	struct rp_info *rp_info; +	struct prefix g; + +	memset(&g, 0, sizeof(g)); +	g.family = AF_INET; +	g.prefixlen = 32; +	g.u.prefix4 = group; + +	rp_info = pim_rp_find_match_group(&g); +	/* +	 * See if we can short-cut some? +	 * This might not make sense if we ever leave a static RP +	 * type of configuration. +	 * Note - Premature optimization might bite our patooeys' here. +	 */ +	if (I_am_RP(group)) { +		if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) +			return 1; +	} + +	if (if_lookup_exact_address(&dest_addr, AF_INET, VRF_DEFAULT)) +		return 1; + +	return 0;  } -void -pim_rp_show_information (struct vty *vty, u_char uj) +void pim_rp_show_information(struct vty *vty, u_char uj)  { -  struct rp_info *rp_info; -  struct rp_info *prev_rp_info = NULL; -  struct listnode *node; - -  json_object *json = NULL; -  json_object *json_rp_rows = NULL; -  json_object *json_row = NULL; - -  if (uj) -    json = json_object_new_object(); -  else -    vty_out (vty, -               "RP address       group/prefix-list   OIF         I am RP\n"); - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) -        { -          char buf[48]; - -          if (uj) -            { -              /* -               * If we have moved on to a new RP then add the entry for the previous RP -               */ -              if (prev_rp_info && -                  prev_rp_info->rp.rpf_addr.u.prefix4.s_addr != rp_info->rp.rpf_addr.u.prefix4.s_addr) -                { -                  json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); -                  json_rp_rows = NULL; -                } - -              if (!json_rp_rows) -                  json_rp_rows = json_object_new_array(); - -              json_row = json_object_new_object(); -	      if (rp_info->rp.source_nexthop.interface) -		json_object_string_add(json_row, "outboundInterface", rp_info->rp.source_nexthop.interface->name); - -              if (rp_info->i_am_rp) -                json_object_boolean_true_add(json_row, "iAmRP"); - -              if (rp_info->plist) -                json_object_string_add(json_row, "prefixList", rp_info->plist); -              else -                json_object_string_add(json_row, "group", prefix2str(&rp_info->group, buf, 48)); - -              json_object_array_add(json_rp_rows, json_row); -            } -          else -            { -              vty_out (vty, "%-15s  ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4)); - -              if (rp_info->plist) -                vty_out (vty, "%-18s  ", rp_info->plist); -              else -                vty_out (vty, "%-18s  ", prefix2str(&rp_info->group, buf, 48)); - -	      if (rp_info->rp.source_nexthop.interface) -		vty_out (vty, "%-10s  ", rp_info->rp.source_nexthop.interface->name); -	      else -		vty_out (vty, "%-10s  ", "(Unknown)"); - -              if (rp_info->i_am_rp) -                vty_out (vty, "yes\n"); -              else -                vty_out (vty, "no\n"); -            } - -          prev_rp_info = rp_info; -        } -    } - -  if (uj) { -    if (prev_rp_info && json_rp_rows) -      json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); - -    vty_out (vty, "%s\n", -               json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); -    json_object_free(json); -  } +	struct rp_info *rp_info; +	struct rp_info *prev_rp_info = NULL; +	struct listnode *node; + +	json_object *json = NULL; +	json_object *json_rp_rows = NULL; +	json_object *json_row = NULL; + +	if (uj) +		json = json_object_new_object(); +	else +		vty_out(vty, +			"RP address       group/prefix-list   OIF         I am RP\n"); + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) { +			char buf[48]; + +			if (uj) { +				/* +				 * If we have moved on to a new RP then add the +				 * entry for the previous RP +				 */ +				if (prev_rp_info +				    && prev_rp_info->rp.rpf_addr.u.prefix4 +						       .s_addr +					       != rp_info->rp.rpf_addr.u.prefix4 +							  .s_addr) { +					json_object_object_add( +						json, +						inet_ntoa(prev_rp_info->rp +								  .rpf_addr.u +								  .prefix4), +						json_rp_rows); +					json_rp_rows = NULL; +				} + +				if (!json_rp_rows) +					json_rp_rows = json_object_new_array(); + +				json_row = json_object_new_object(); +				if (rp_info->rp.source_nexthop.interface) +					json_object_string_add( +						json_row, "outboundInterface", +						rp_info->rp.source_nexthop +							.interface->name); + +				if (rp_info->i_am_rp) +					json_object_boolean_true_add(json_row, +								     "iAmRP"); + +				if (rp_info->plist) +					json_object_string_add(json_row, +							       "prefixList", +							       rp_info->plist); +				else +					json_object_string_add( +						json_row, "group", +						prefix2str(&rp_info->group, buf, +							   48)); + +				json_object_array_add(json_rp_rows, json_row); +			} else { +				vty_out(vty, "%-15s  ", +					inet_ntoa(rp_info->rp.rpf_addr.u +							  .prefix4)); + +				if (rp_info->plist) +					vty_out(vty, "%-18s  ", rp_info->plist); +				else +					vty_out(vty, "%-18s  ", +						prefix2str(&rp_info->group, buf, +							   48)); + +				if (rp_info->rp.source_nexthop.interface) +					vty_out(vty, "%-10s  ", +						rp_info->rp.source_nexthop +							.interface->name); +				else +					vty_out(vty, "%-10s  ", "(Unknown)"); + +				if (rp_info->i_am_rp) +					vty_out(vty, "yes\n"); +				else +					vty_out(vty, "no\n"); +			} + +			prev_rp_info = rp_info; +		} +	} + +	if (uj) { +		if (prev_rp_info && json_rp_rows) +			json_object_object_add( +				json, +				inet_ntoa(prev_rp_info->rp.rpf_addr.u.prefix4), +				json_rp_rows); + +		vty_out(vty, "%s\n", json_object_to_json_string_ext( +					     json, JSON_C_TO_STRING_PRETTY)); +		json_object_free(json); +	}  } -void -pim_resolve_rp_nh (void) +void pim_resolve_rp_nh(void)  { -  struct listnode *node = NULL; -  struct rp_info *rp_info = NULL; -  struct nexthop *nh_node = NULL; -  struct prefix nht_p; -  struct pim_nexthop_cache pnc; -  struct pim_neighbor *nbr = NULL; - -  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) -    { -      if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) -        continue; - -      nht_p.family = AF_INET; -      nht_p.prefixlen = IPV4_MAX_BITLEN; -      nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; -      memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -      if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) -        { -          for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) -            { -              if (nh_node->gate.ipv4.s_addr == 0) -                { -                  nbr = pim_neighbor_find_if (if_lookup_by_index -                                          (nh_node->ifindex, VRF_DEFAULT)); -                  if (nbr) -                    { -                      nh_node->gate.ipv4 = nbr->source_addr; -                      if (PIM_DEBUG_TRACE) -                        { -                          char str[PREFIX_STRLEN]; -                          char str1[INET_ADDRSTRLEN]; -                          struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex, -                                                                              VRF_DEFAULT); -                          pim_inet4_dump ("<nht_nbr?>", nbr->source_addr, -                                          str1, sizeof (str1)); -                          pim_addr_dump ("<nht_addr?>", &nht_p, str, -                                         sizeof (str)); -                          zlog_debug ("%s: addr %s new nexthop addr %s interface %s", -                             __PRETTY_FUNCTION__, str, str1, -                             ifp1->name); -                        } -                    } -                } -            } -        } -    } +	struct listnode *node = NULL; +	struct rp_info *rp_info = NULL; +	struct nexthop *nh_node = NULL; +	struct prefix nht_p; +	struct pim_nexthop_cache pnc; +	struct pim_neighbor *nbr = NULL; + +	for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { +		if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) +			continue; + +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; +		memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +		if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) +		    == 1) { +			for (nh_node = pnc.nexthop; nh_node; +			     nh_node = nh_node->next) { +				if (nh_node->gate.ipv4.s_addr == 0) { +					nbr = pim_neighbor_find_if( +						if_lookup_by_index( +							nh_node->ifindex, +							VRF_DEFAULT)); +					if (nbr) { +						nh_node->gate.ipv4 = +							nbr->source_addr; +						if (PIM_DEBUG_TRACE) { +							char str[PREFIX_STRLEN]; +							char str1 +								[INET_ADDRSTRLEN]; +							struct interface *ifp1 = +								if_lookup_by_index( +									nh_node->ifindex, +									VRF_DEFAULT); +							pim_inet4_dump( +								"<nht_nbr?>", +								nbr->source_addr, +								str1, +								sizeof(str1)); +							pim_addr_dump( +								"<nht_addr?>", +								&nht_p, str, +								sizeof(str)); +							zlog_debug( +								"%s: addr %s new nexthop addr %s interface %s", +								__PRETTY_FUNCTION__, +								str, str1, +								ifp1->name); +						} +					} +				} +			} +		} +	}  } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 319fe573ca..7a7c26593e 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -27,39 +27,40 @@  #include "pim_iface.h"  #include "pim_rpf.h" -struct rp_info -{ -  struct prefix group; -  struct pim_rpf rp; -  int i_am_rp; -  char *plist; +struct rp_info { +	struct prefix group; +	struct pim_rpf rp; +	int i_am_rp; +	char *plist;  }; -void pim_rp_init (void); -void pim_rp_free (void); +void pim_rp_init(void); +void pim_rp_free(void); -int pim_rp_new (const char *rp, const char *group, const char *plist); -int pim_rp_del (const char *rp, const char *group, const char *plist); -void pim_rp_prefix_list_update (struct prefix_list *plist); +int pim_rp_new(const char *rp, const char *group, const char *plist); +int pim_rp_del(const char *rp, const char *group, const char *plist); +void pim_rp_prefix_list_update(struct prefix_list *plist); -int pim_rp_config_write (struct vty *vty); +int pim_rp_config_write(struct vty *vty); -int pim_rp_setup (void); +int pim_rp_setup(void); -int pim_rp_i_am_rp (struct in_addr group); +int pim_rp_i_am_rp(struct in_addr group);  void pim_rp_check_on_if_add(struct pim_interface *pim_ifp);  void pim_i_am_rp_re_evaluate(void); -int pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr); +int pim_rp_check_is_my_ip_address(struct in_addr group, +				  struct in_addr dest_addr); -int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group); +int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source, +			     struct in_addr group); -struct pim_rpf *pim_rp_g (struct in_addr group); +struct pim_rpf *pim_rp_g(struct in_addr group);  #define I_am_RP(G)  pim_rp_i_am_rp ((G))  #define RP(G)       pim_rp_g ((G)) -void pim_rp_show_information (struct vty *vty, u_char uj); -void pim_resolve_rp_nh (void); -int pim_rp_list_cmp (void *v1, void *v2); +void pim_rp_show_information(struct vty *vty, u_char uj); +void pim_resolve_rp_nh(void); +int pim_rp_list_cmp(void *v1, void *v2);  #endif diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index c5adf423c4..4d0652c27e 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -38,285 +38,281 @@  static long long last_route_change_time = -1;  long long nexthop_lookups_avoided = 0; -static struct in_addr pim_rpf_find_rpf_addr (struct pim_upstream *up); +static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); -void -pim_rpf_set_refresh_time (void) +void pim_rpf_set_refresh_time(void)  { -  last_route_change_time = pim_time_monotonic_usec(); -  if (PIM_DEBUG_TRACE) -    zlog_debug ("%s: New last route change time: %lld", -		__PRETTY_FUNCTION__, last_route_change_time); +	last_route_change_time = pim_time_monotonic_usec(); +	if (PIM_DEBUG_TRACE) +		zlog_debug("%s: New last route change time: %lld", +			   __PRETTY_FUNCTION__, last_route_change_time);  } -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed) +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, +		       int neighbor_needed)  { -  struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; -  struct pim_neighbor *nbr = NULL; -  int num_ifindex; -  struct interface *ifp = NULL; -  ifindex_t first_ifindex = 0; -  int found = 0; -  int i = 0; - -  if ((nexthop->last_lookup.s_addr == addr.s_addr) && -      (nexthop->last_lookup_time > last_route_change_time)) -    { -      if (PIM_DEBUG_TRACE) -	{ -	  char addr_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -          char nexthop_str[PREFIX_STRLEN]; -          pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr, -                            nexthop_str, sizeof(nexthop_str)); -          zlog_debug ("%s: Using last lookup for %s at %lld, %lld addr%s", -		      __PRETTY_FUNCTION__, -		      addr_str, -		      nexthop->last_lookup_time, -		      last_route_change_time, nexthop_str); +	struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; +	struct pim_neighbor *nbr = NULL; +	int num_ifindex; +	struct interface *ifp = NULL; +	ifindex_t first_ifindex = 0; +	int found = 0; +	int i = 0; + +	if ((nexthop->last_lookup.s_addr == addr.s_addr) +	    && (nexthop->last_lookup_time > last_route_change_time)) { +		if (PIM_DEBUG_TRACE) { +			char addr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			char nexthop_str[PREFIX_STRLEN]; +			pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr, +				      nexthop_str, sizeof(nexthop_str)); +			zlog_debug( +				"%s: Using last lookup for %s at %lld, %lld addr%s", +				__PRETTY_FUNCTION__, addr_str, +				nexthop->last_lookup_time, +				last_route_change_time, nexthop_str); +		} +		nexthop_lookups_avoided++; +		return 0; +	} else { +		if (PIM_DEBUG_TRACE) { +			char addr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			zlog_debug( +				"%s: Looking up: %s, last lookup time: %lld, %lld", +				__PRETTY_FUNCTION__, addr_str, +				nexthop->last_lookup_time, +				last_route_change_time); +		}  	} -      nexthop_lookups_avoided++; -      return 0; -    } -  else -    { -      if (PIM_DEBUG_TRACE) -	{ -	  char addr_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -	  zlog_debug ("%s: Looking up: %s, last lookup time: %lld, %lld", -		      __PRETTY_FUNCTION__, -		      addr_str, -		      nexthop->last_lookup_time, -		      last_route_change_time); + +	memset(nexthop_tab, 0, +	       sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); +	num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, +					     PIM_NEXTHOP_LOOKUP_MAX); +	if (num_ifindex < 1) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_warn( +			"%s %s: could not find nexthop ifindex for address %s", +			__FILE__, __PRETTY_FUNCTION__, addr_str); +		return -1; +	} + +	while (!found && (i < num_ifindex)) { +		first_ifindex = nexthop_tab[i].ifindex; + +		ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); +		if (!ifp) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s %s: could not find interface for ifindex %d (address %s)", +					__FILE__, __PRETTY_FUNCTION__, +					first_ifindex, addr_str); +			} +			i++; +			continue; +		} + +		if (!ifp->info) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", +					__PRETTY_FUNCTION__, ifp->name, +					first_ifindex, addr_str); +			} +			i++; +		} else if (neighbor_needed +			   && !pim_if_connected_to_source(ifp, addr)) { +			nbr = pim_neighbor_find( +				ifp, nexthop_tab[i].nexthop_addr.u.prefix4); +			if (PIM_DEBUG_PIM_TRACE_DETAIL) +				zlog_debug("ifp name: %s, pim nbr: %p", +					   ifp->name, nbr); +			if (!nbr && !if_is_loopback(ifp)) +				i++; +			else +				found = 1; +		} else +			found = 1;  	} -    } - -  memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); -  num_ifindex = zclient_lookup_nexthop(nexthop_tab, -				       MULTIPATH_NUM, -				       addr, PIM_NEXTHOP_LOOKUP_MAX); -  if (num_ifindex < 1) { -    char addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -    zlog_warn("%s %s: could not find nexthop ifindex for address %s", -	      __FILE__, __PRETTY_FUNCTION__, -	      addr_str); -    return -1; -  } - -  while (!found && (i < num_ifindex)) -    { -      first_ifindex = nexthop_tab[i].ifindex; - -      ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); -      if (!ifp) -        { -          if (PIM_DEBUG_ZEBRA) -            { -              char addr_str[INET_ADDRSTRLEN]; -              pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -              zlog_debug("%s %s: could not find interface for ifindex %d (address %s)", -                         __FILE__, __PRETTY_FUNCTION__, -                         first_ifindex, addr_str); -            } -	  i++; -	  continue; -        } - -      if (!ifp->info) -        { -	  if (PIM_DEBUG_ZEBRA) -	    { -	      char addr_str[INET_ADDRSTRLEN]; -	      pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -	      zlog_debug("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", -			 __PRETTY_FUNCTION__, -			 ifp->name, first_ifindex, addr_str); -	    } -	  i++; -        } -      else if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) -        { -          nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); -          if (PIM_DEBUG_PIM_TRACE_DETAIL) -            zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); -          if (!nbr && !if_is_loopback (ifp)) -            i++; -          else -            found = 1; -        } -      else -        found = 1; -    } - -  if (found) -    { -      if (PIM_DEBUG_ZEBRA) { -        char nexthop_str[PREFIX_STRLEN]; -        char addr_str[INET_ADDRSTRLEN]; -        pim_addr_dump("<nexthop?>", &nexthop_tab[i].nexthop_addr, nexthop_str, sizeof(nexthop_str)); -        pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -        zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", -	           __FILE__, __PRETTY_FUNCTION__, -	           nexthop_str, addr_str, -	           ifp->name, first_ifindex, -	           nexthop_tab[i].route_metric, -	           nexthop_tab[i].protocol_distance); -      } -      /* update nextop data */ -      nexthop->interface                = ifp; -      nexthop->mrib_nexthop_addr        = nexthop_tab[i].nexthop_addr; -      nexthop->mrib_metric_preference   = nexthop_tab[i].protocol_distance; -      nexthop->mrib_route_metric        = nexthop_tab[i].route_metric; -      nexthop->last_lookup              = addr; -      nexthop->last_lookup_time         = pim_time_monotonic_usec(); -      nexthop->nbr                      = nbr; -      return 0; -    } -  else -    return -1; + +	if (found) { +		if (PIM_DEBUG_ZEBRA) { +			char nexthop_str[PREFIX_STRLEN]; +			char addr_str[INET_ADDRSTRLEN]; +			pim_addr_dump("<nexthop?>", +				      &nexthop_tab[i].nexthop_addr, nexthop_str, +				      sizeof(nexthop_str)); +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			zlog_debug( +				"%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", +				__FILE__, __PRETTY_FUNCTION__, nexthop_str, +				addr_str, ifp->name, first_ifindex, +				nexthop_tab[i].route_metric, +				nexthop_tab[i].protocol_distance); +		} +		/* update nextop data */ +		nexthop->interface = ifp; +		nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; +		nexthop->mrib_metric_preference = +			nexthop_tab[i].protocol_distance; +		nexthop->mrib_route_metric = nexthop_tab[i].route_metric; +		nexthop->last_lookup = addr; +		nexthop->last_lookup_time = pim_time_monotonic_usec(); +		nexthop->nbr = nbr; +		return 0; +	} else +		return -1;  }  static int nexthop_mismatch(const struct pim_nexthop *nh1,  			    const struct pim_nexthop *nh2)  { -  return (nh1->interface != nh2->interface)                          || -    (nh1->mrib_nexthop_addr.u.prefix4.s_addr != nh2->mrib_nexthop_addr.u.prefix4.s_addr) || -    (nh1->mrib_metric_preference != nh2->mrib_metric_preference)     || -    (nh1->mrib_route_metric != nh2->mrib_route_metric); +	return (nh1->interface != nh2->interface) +	       || (nh1->mrib_nexthop_addr.u.prefix4.s_addr +		   != nh2->mrib_nexthop_addr.u.prefix4.s_addr) +	       || (nh1->mrib_metric_preference != nh2->mrib_metric_preference) +	       || (nh1->mrib_route_metric != nh2->mrib_route_metric);  } -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new) +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, +				   uint8_t is_new)  { -  struct pim_rpf     *rpf = &up->rpf; -  struct pim_rpf     saved; -  struct prefix     nht_p; -  struct pim_nexthop_cache pnc; -  int ret = 0; -  struct prefix src, grp; - -  saved.source_nexthop = rpf->source_nexthop; -  saved.rpf_addr = rpf->rpf_addr; - -  if (is_new && PIM_DEBUG_ZEBRA) -    { -      char source_str[INET_ADDRSTRLEN]; -      pim_inet4_dump ("<source?>", up->upstream_addr, source_str, -                      sizeof (source_str)); -      zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.", -                  __PRETTY_FUNCTION__, up->sg_str, source_str); -    } -  /* Register addr with Zebra NHT */ -  nht_p.family = AF_INET; -  nht_p.prefixlen = IPV4_MAX_BITLEN; -  nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - -  src.family = AF_INET; -  src.prefixlen = IPV4_MAX_BITLEN; -  src.u.prefix4 = up->upstream_addr;    //RP or Src address -  grp.family = AF_INET; -  grp.prefixlen = IPV4_MAX_BITLEN; -  grp.u.prefix4 = up->sg.grp; -  memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); -  if ((ret = pim_find_or_track_nexthop (&nht_p, up, NULL, &pnc)) == 1) -    { -      if (pnc.nexthop_num) -        { -          //Compute PIM RPF using Cached nexthop -          if (pim_ecmp_nexthop_search (&pnc, &up->rpf.source_nexthop, -                                       &src, &grp, -                                       !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && -                                       !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) - -            { -              return PIM_RPF_FAILURE; -            } -        } -    } -  else -    { -      if (pim_ecmp_nexthop_lookup (&rpf->source_nexthop, -                                   up->upstream_addr, &src, &grp, -                                   !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && -                                   !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) -        { -          return PIM_RPF_FAILURE; -        } -    } - -  rpf->rpf_addr.family = AF_INET; -  rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); -  if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) -    { -      /* RPF'(S,G) not found */ -      zlog_debug("%s %s: RPF'%s not found: won't send join upstream", -	       __FILE__, __PRETTY_FUNCTION__, -	       up->sg_str); -      /* warning only */ -    } - -  /* detect change in pim_nexthop */ -  if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { - -    if (PIM_DEBUG_ZEBRA) { -      char nhaddr_str[PREFIX_STRLEN]; -      pim_addr_dump("<addr?>", &rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); -      zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", +	struct pim_rpf *rpf = &up->rpf; +	struct pim_rpf saved; +	struct prefix nht_p; +	struct pim_nexthop_cache pnc; +	int ret = 0; +	struct prefix src, grp; + +	saved.source_nexthop = rpf->source_nexthop; +	saved.rpf_addr = rpf->rpf_addr; + +	if (is_new && PIM_DEBUG_ZEBRA) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<source?>", up->upstream_addr, source_str, +			       sizeof(source_str)); +		zlog_debug("%s: NHT Register upstream %s addr %s with Zebra.", +			   __PRETTY_FUNCTION__, up->sg_str, source_str); +	} +	/* Register addr with Zebra NHT */ +	nht_p.family = AF_INET; +	nht_p.prefixlen = IPV4_MAX_BITLEN; +	nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + +	src.family = AF_INET; +	src.prefixlen = IPV4_MAX_BITLEN; +	src.u.prefix4 = up->upstream_addr; // RP or Src address +	grp.family = AF_INET; +	grp.prefixlen = IPV4_MAX_BITLEN; +	grp.u.prefix4 = up->sg.grp; +	memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); +	if ((ret = pim_find_or_track_nexthop(&nht_p, up, NULL, &pnc)) == 1) { +		if (pnc.nexthop_num) { +			// Compute PIM RPF using Cached nexthop +			if (pim_ecmp_nexthop_search( +				    &pnc, &up->rpf.source_nexthop, &src, &grp, +				    !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) +					    && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( +						       up->flags))) + +			{ +				return PIM_RPF_FAILURE; +			} +		} +	} else { +		if (pim_ecmp_nexthop_lookup( +			    &rpf->source_nexthop, up->upstream_addr, &src, &grp, +			    !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) +				    && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( +					       up->flags))) { +			return PIM_RPF_FAILURE; +		} +	} + +	rpf->rpf_addr.family = AF_INET; +	rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); +	if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) { +		/* RPF'(S,G) not found */ +		zlog_debug("%s %s: RPF'%s not found: won't send join upstream", +			   __FILE__, __PRETTY_FUNCTION__, up->sg_str); +		/* warning only */ +	} + +	/* detect change in pim_nexthop */ +	if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { + +		if (PIM_DEBUG_ZEBRA) { +			char nhaddr_str[PREFIX_STRLEN]; +			pim_addr_dump("<addr?>", +				      &rpf->source_nexthop.mrib_nexthop_addr, +				      nhaddr_str, sizeof(nhaddr_str)); +			zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d",  		 __FILE__, __PRETTY_FUNCTION__,  		 up->sg_str,  		 rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>",  		 nhaddr_str,  		 rpf->source_nexthop.mrib_metric_preference,  		 rpf->source_nexthop.mrib_route_metric); -    } +		} -    pim_upstream_update_join_desired(up); -    pim_upstream_update_could_assert(up); -    pim_upstream_update_my_assert_metric(up); -  } +		pim_upstream_update_join_desired(up); +		pim_upstream_update_could_assert(up); +		pim_upstream_update_my_assert_metric(up); +	} -  /* detect change in RPF_interface(S) */ -  if (saved.source_nexthop.interface != rpf->source_nexthop.interface) { +	/* detect change in RPF_interface(S) */ +	if (saved.source_nexthop.interface != rpf->source_nexthop.interface) { -    if (PIM_DEBUG_ZEBRA) { -      zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", +		if (PIM_DEBUG_ZEBRA) { +			zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s",  		 __FILE__, __PRETTY_FUNCTION__,  		 up->sg_str,  		 saved.source_nexthop.interface ? saved.source_nexthop.interface->name : "<oldif?>",  		 rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<newif?>"); -      /* warning only */ -    } - -    pim_upstream_rpf_interface_changed(up, saved.source_nexthop.interface); -  } - -  /* detect change in RPF'(S,G) */ -  if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr || -      saved.source_nexthop.interface != rpf->source_nexthop.interface) -    { - -    /* return old rpf to caller ? */ -    if (old) -      { -        old->source_nexthop = saved.source_nexthop; -        old->rpf_addr = saved.rpf_addr; -      } -    return PIM_RPF_CHANGED; -  } - -  return PIM_RPF_OK; +			/* warning only */ +		} + +		pim_upstream_rpf_interface_changed( +			up, saved.source_nexthop.interface); +	} + +	/* detect change in RPF'(S,G) */ +	if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr +	    || saved.source_nexthop +			       .interface != rpf->source_nexthop.interface) { + +		/* return old rpf to caller ? */ +		if (old) { +			old->source_nexthop = saved.source_nexthop; +			old->rpf_addr = saved.rpf_addr; +		} +		return PIM_RPF_CHANGED; +	} + +	return PIM_RPF_OK;  }  /*    RFC 4601: 4.1.6.  State Summarization Macros       neighbor RPF'(S,G) { -         if ( I_Am_Assert_Loser(S, G, RPF_interface(S) )) { -              return AssertWinner(S, G, RPF_interface(S) ) -         } else { -              return NBR( RPF_interface(S), MRIB.next_hop( S ) ) -         } +	 if ( I_Am_Assert_Loser(S, G, RPF_interface(S) )) { +	      return AssertWinner(S, G, RPF_interface(S) ) +	 } else { +	      return NBR( RPF_interface(S), MRIB.next_hop( S ) ) +	 }       }    RPF'(*,G) and RPF'(S,G) indicate the neighbor from which data @@ -325,84 +321,78 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,  */  static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up)  { -  struct pim_ifchannel *rpf_ch; -  struct pim_neighbor *neigh; -  struct in_addr rpf_addr; - -  if (!up->rpf.source_nexthop.interface) { -    zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", -	      __PRETTY_FUNCTION__, -	      up->sg_str); - -    rpf_addr.s_addr = PIM_NET_INADDR_ANY; -    return rpf_addr; -  } - -  rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, -			      &up->sg); -  if (rpf_ch) { -    if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { -      return rpf_ch->ifassert_winner; -    } -  } - -  /* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ - -  neigh = pim_if_find_neighbor(up->rpf.source_nexthop.interface, -			       up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4); -  if (neigh) -    rpf_addr = neigh->source_addr; -  else -    rpf_addr.s_addr = PIM_NET_INADDR_ANY; - -  return rpf_addr; +	struct pim_ifchannel *rpf_ch; +	struct pim_neighbor *neigh; +	struct in_addr rpf_addr; + +	if (!up->rpf.source_nexthop.interface) { +		zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", +			  __PRETTY_FUNCTION__, up->sg_str); + +		rpf_addr.s_addr = PIM_NET_INADDR_ANY; +		return rpf_addr; +	} + +	rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, &up->sg); +	if (rpf_ch) { +		if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { +			return rpf_ch->ifassert_winner; +		} +	} + +	/* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ + +	neigh = pim_if_find_neighbor( +		up->rpf.source_nexthop.interface, +		up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4); +	if (neigh) +		rpf_addr = neigh->source_addr; +	else +		rpf_addr.s_addr = PIM_NET_INADDR_ANY; + +	return rpf_addr;  } -int -pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf) +int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf)  { -  switch (rpf->rpf_addr.family) -    { -    case AF_INET: -      return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; -      break; -    case AF_INET6: -      zlog_warn ("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); -      return 1; -      break; -    default: -      return 0; -      break; -    } - -  return 0; +	switch (rpf->rpf_addr.family) { +	case AF_INET: +		return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; +		break; +	case AF_INET6: +		zlog_warn("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); +		return 1; +		break; +	default: +		return 0; +		break; +	} + +	return 0;  } -int -pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf) +int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf)  { -  switch (rpf->rpf_addr.family) -    { -    case AF_INET: -      return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; -      break; -    case AF_INET6: -      zlog_warn ("%s: v6 Unimplmented", __PRETTY_FUNCTION__); -      return 1; -      break; -    default: -      return 0; -      break; -    } - -  return 0; +	switch (rpf->rpf_addr.family) { +	case AF_INET: +		return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; +		break; +	case AF_INET6: +		zlog_warn("%s: v6 Unimplmented", __PRETTY_FUNCTION__); +		return 1; +		break; +	default: +		return 0; +		break; +	} + +	return 0;  } -int -pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2) +int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2)  { -  if (rpf1->source_nexthop.interface == rpf2->source_nexthop.interface) -    return 1; +	if (rpf1->source_nexthop.interface == rpf2->source_nexthop.interface) +		return 1; -  return 0; +	return 0;  } diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index bb7ee365b1..0833143563 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -38,36 +38,34 @@      units applicable to the unicast routing protocol used.  */  struct pim_nexthop { -  struct in_addr    last_lookup; -  long long         last_lookup_time; -  struct interface *interface;              /* RPF_interface(S) */ -  struct prefix     mrib_nexthop_addr;      /* MRIB.next_hop(S) */ -  uint32_t          mrib_metric_preference; /* MRIB.pref(S) */ -  uint32_t          mrib_route_metric;      /* MRIB.metric(S) */ -  struct pim_neighbor *nbr; +	struct in_addr last_lookup; +	long long last_lookup_time; +	struct interface *interface;     /* RPF_interface(S) */ +	struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ +	uint32_t mrib_metric_preference; /* MRIB.pref(S) */ +	uint32_t mrib_route_metric;      /* MRIB.metric(S) */ +	struct pim_neighbor *nbr;  };  struct pim_rpf { -  struct pim_nexthop source_nexthop; -  struct prefix      rpf_addr;               /* RPF'(S,G) */ +	struct pim_nexthop source_nexthop; +	struct prefix rpf_addr; /* RPF'(S,G) */  }; -enum pim_rpf_result { -  PIM_RPF_OK = 0, -  PIM_RPF_CHANGED, -  PIM_RPF_FAILURE -}; +enum pim_rpf_result { PIM_RPF_OK = 0, PIM_RPF_CHANGED, PIM_RPF_FAILURE };  struct pim_upstream;  extern long long nexthop_lookups_avoided; -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed); -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new); +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, +		       int neighbor_needed); +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, +				   uint8_t is_new); -int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); -int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf); +int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf); +int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf); -int pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2); -void pim_rpf_set_refresh_time (void); +int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2); +void pim_rpf_set_refresh_time(void);  #endif /* PIM_RPF_H */ diff --git a/pimd/pim_signals.c b/pimd/pim_signals.c index ef492d0d83..0e9b09bf84 100644 --- a/pimd/pim_signals.c +++ b/pimd/pim_signals.c @@ -35,44 +35,43 @@  static void pim_sighup()  { -  zlog_info ("SIGHUP received, ignoring"); +	zlog_info("SIGHUP received, ignoring");  }  static void pim_sigint()  { -  zlog_notice("Terminating on signal SIGINT"); -  pim_terminate(); -  exit(1); +	zlog_notice("Terminating on signal SIGINT"); +	pim_terminate(); +	exit(1);  }  static void pim_sigterm()  { -  zlog_notice("Terminating on signal SIGTERM"); -  pim_terminate(); -  exit(1); +	zlog_notice("Terminating on signal SIGTERM"); +	pim_terminate(); +	exit(1);  }  static void pim_sigusr1()  { -  zlog_rotate(); +	zlog_rotate();  } -struct quagga_signal_t pimd_signals[] = -{ -  { -   .signal = SIGHUP, -   .handler = &pim_sighup, -   }, -  { -   .signal = SIGUSR1, -   .handler = &pim_sigusr1, -   }, -  { -   .signal = SIGINT, -   .handler = &pim_sigint, -   }, -  { -   .signal = SIGTERM, -   .handler = &pim_sigterm, -   }, +struct quagga_signal_t pimd_signals[] = { +	{ +		.signal = SIGHUP, +		.handler = &pim_sighup, +	}, +	{ +		.signal = SIGUSR1, +		.handler = &pim_sigusr1, +	}, +	{ +		.signal = SIGINT, +		.handler = &pim_sigint, +	}, +	{ +		.signal = SIGTERM, +		.handler = &pim_sigterm, +	},  }; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index ba70cf2e11..a4d3d7e4b3 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -42,292 +42,305 @@  /* GLOBAL VARS */ -int -pim_socket_raw (int protocol) +int pim_socket_raw(int protocol)  { -  int fd; +	int fd; -  if ( pimd_privs.change (ZPRIVS_RAISE) ) -       zlog_err ("pim_sockek_raw: could not raise privs, %s", -                 safe_strerror (errno) ); +	if (pimd_privs.change(ZPRIVS_RAISE)) +		zlog_err("pim_sockek_raw: could not raise privs, %s", +			 safe_strerror(errno)); -  fd = socket(AF_INET, SOCK_RAW, protocol); +	fd = socket(AF_INET, SOCK_RAW, protocol); -  if ( pimd_privs.change (ZPRIVS_LOWER) ) -       zlog_err ("pim_socket_raw: could not lower privs, %s", -                 safe_strerror (errno) ); +	if (pimd_privs.change(ZPRIVS_LOWER)) +		zlog_err("pim_socket_raw: could not lower privs, %s", +			 safe_strerror(errno)); -  if (fd < 0) { -    zlog_warn("Could not create raw socket: errno=%d: %s", -	      errno, safe_strerror(errno)); -    return PIM_SOCK_ERR_SOCKET; -  } -   -  return fd; +	if (fd < 0) { +		zlog_warn("Could not create raw socket: errno=%d: %s", errno, +			  safe_strerror(errno)); +		return PIM_SOCK_ERR_SOCKET; +	} + +	return fd;  } -int -pim_socket_ip_hdr (int fd) +int pim_socket_ip_hdr(int fd)  { -  const int on = 1; -  int ret; +	const int on = 1; +	int ret; -  if (pimd_privs.change (ZPRIVS_RAISE)) -    zlog_err ("%s: could not raise privs, %s", -	      __PRETTY_FUNCTION__, safe_strerror (errno)); +	if (pimd_privs.change(ZPRIVS_RAISE)) +		zlog_err("%s: could not raise privs, %s", __PRETTY_FUNCTION__, +			 safe_strerror(errno)); -  ret = setsockopt (fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)); +	ret = setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)); -  if (pimd_privs.change (ZPRIVS_LOWER)) -    zlog_err ("%s: could not lower privs, %s", -	      __PRETTY_FUNCTION__, safe_strerror (errno)); +	if (pimd_privs.change(ZPRIVS_LOWER)) +		zlog_err("%s: could not lower privs, %s", __PRETTY_FUNCTION__, +			 safe_strerror(errno)); -  return ret; +	return ret;  }  /*   * Given a socket and a interface,   * Bind that socket to that interface   */ -int -pim_socket_bind (int fd, struct interface *ifp) +int pim_socket_bind(int fd, struct interface *ifp)  { -  int ret = 0; +	int ret = 0;  #ifdef SO_BINDTODEVICE -  if (pimd_privs.change (ZPRIVS_RAISE)) -    zlog_err ("%s: could not raise privs, %s", -	      __PRETTY_FUNCTION__, safe_strerror (errno)); +	if (pimd_privs.change(ZPRIVS_RAISE)) +		zlog_err("%s: could not raise privs, %s", __PRETTY_FUNCTION__, +			 safe_strerror(errno)); -  ret = setsockopt (fd, SOL_SOCKET, -		    SO_BINDTODEVICE, ifp->name, strlen (ifp->name)); +	ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifp->name, +			 strlen(ifp->name)); -  if (pimd_privs.change (ZPRIVS_LOWER)) -    zlog_err ("%s: could not lower privs, %s", -	      __PRETTY_FUNCTION__, safe_strerror (errno)); +	if (pimd_privs.change(ZPRIVS_LOWER)) +		zlog_err("%s: could not lower privs, %s", __PRETTY_FUNCTION__, +			 safe_strerror(errno));  #endif -  return ret; +	return ret;  } -int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, u_char loop) +int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, +		     u_char loop)  { -  int rcvbuf = 1024 * 1024 * 8; +	int rcvbuf = 1024 * 1024 * 8;  #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX -  struct ip_mreqn mreq; +	struct ip_mreqn mreq;  #else -  struct ip_mreq mreq; +	struct ip_mreq mreq;  #endif -  int fd; +	int fd; -  fd = pim_socket_raw(protocol); -  if (fd < 0) { -    zlog_warn("Could not create multicast socket: errno=%d: %s", -	      errno, safe_strerror(errno)); -    return PIM_SOCK_ERR_SOCKET; -  } +	fd = pim_socket_raw(protocol); +	if (fd < 0) { +		zlog_warn("Could not create multicast socket: errno=%d: %s", +			  errno, safe_strerror(errno)); +		return PIM_SOCK_ERR_SOCKET; +	}  #ifdef SO_BINDTODEVICE -  if (protocol == IPPROTO_PIM) -    { -      int ret; - -      ret = pim_socket_bind (fd, ifp); -      if (ret) -	{ -          close (fd); -	  zlog_warn("Could not set fd: %d for interface: %s to device", -		    fd, ifp->name); -	  return PIM_SOCK_ERR_BIND; +	if (protocol == IPPROTO_PIM) { +		int ret; + +		ret = pim_socket_bind(fd, ifp); +		if (ret) { +			close(fd); +			zlog_warn( +				"Could not set fd: %d for interface: %s to device", +				fd, ifp->name); +			return PIM_SOCK_ERR_BIND; +		}  	} -    }  #else -  /* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour?  Or change to -   * only use 1 socket for all interfaces? */ +/* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour?  Or change to + * only use 1 socket for all interfaces? */  #endif -  /* Needed to obtain destination address from recvmsg() */ -  { +	/* Needed to obtain destination address from recvmsg() */ +	{  #if defined(HAVE_IP_PKTINFO) -    /* Linux and Solaris IP_PKTINFO */ -    int opt = 1; -    if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { -      zlog_warn("Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", -		fd, errno, safe_strerror(errno)); -    } +		/* Linux and Solaris IP_PKTINFO */ +		int opt = 1; +		if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { +			zlog_warn( +				"Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", +				fd, errno, safe_strerror(errno)); +		}  #elif defined(HAVE_IP_RECVDSTADDR) -    /* BSD IP_RECVDSTADDR */ -    int opt = 1; -    if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) { -      zlog_warn("Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", -		fd, errno, safe_strerror(errno)); -    } +		/* BSD IP_RECVDSTADDR */ +		int opt = 1; +		if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, +			       sizeof(opt))) { +			zlog_warn( +				"Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", +				fd, errno, safe_strerror(errno)); +		}  #else -    zlog_err("%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", -	     __FILE__, __PRETTY_FUNCTION__); -    close(fd); -    return PIM_SOCK_ERR_DSTADDR; +		zlog_err( +			"%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", +			__FILE__, __PRETTY_FUNCTION__); +		close(fd); +		return PIM_SOCK_ERR_DSTADDR;  #endif -  } - -   -  /* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4. Message Formats)*/ -  if (protocol == IPPROTO_IGMP) { -    uint8_t ra[4]; -    ra[0] = 148; -    ra[1] = 4; -    ra[2] = 0; -    ra[3] = 0; -    if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) { -      zlog_warn("Could not set Router Alert Option on socket fd=%d: errno=%d: %s", -		fd, errno, safe_strerror(errno)); -      close(fd); -      return PIM_SOCK_ERR_RA; -    } -  } - -  { -    int reuse = 1; -    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, -		   (void *) &reuse, sizeof(reuse))) { -      zlog_warn("Could not set Reuse Address Option on socket fd=%d: errno=%d: %s", -		fd, errno, safe_strerror(errno)); -      close(fd); -      return PIM_SOCK_ERR_REUSE; -    } -  } - -  { -    const int MTTL = 1; -    int ttl = MTTL; -    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, -		   (void *) &ttl, sizeof(ttl))) { -      zlog_warn("Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", -		MTTL, fd, errno, safe_strerror(errno)); -      close(fd); -      return PIM_SOCK_ERR_TTL; -    } -  } - -  if (setsockopt_ipv4_multicast_loop (fd, loop)) { -    zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", -	      loop ? "enable" : "disable", -	      fd, errno, safe_strerror(errno)); -    close(fd); -    return PIM_SOCK_ERR_LOOP; -  } - -  memset (&mreq, 0, sizeof (mreq)); +	} + + +	/* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4. +	 * Message Formats)*/ +	if (protocol == IPPROTO_IGMP) { +		uint8_t ra[4]; +		ra[0] = 148; +		ra[1] = 4; +		ra[2] = 0; +		ra[3] = 0; +		if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) { +			zlog_warn( +				"Could not set Router Alert Option on socket fd=%d: errno=%d: %s", +				fd, errno, safe_strerror(errno)); +			close(fd); +			return PIM_SOCK_ERR_RA; +		} +	} + +	{ +		int reuse = 1; +		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, +			       sizeof(reuse))) { +			zlog_warn( +				"Could not set Reuse Address Option on socket fd=%d: errno=%d: %s", +				fd, errno, safe_strerror(errno)); +			close(fd); +			return PIM_SOCK_ERR_REUSE; +		} +	} + +	{ +		const int MTTL = 1; +		int ttl = MTTL; +		if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, +			       sizeof(ttl))) { +			zlog_warn( +				"Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", +				MTTL, fd, errno, safe_strerror(errno)); +			close(fd); +			return PIM_SOCK_ERR_TTL; +		} +	} + +	if (setsockopt_ipv4_multicast_loop(fd, loop)) { +		zlog_warn( +			"Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", +			loop ? "enable" : "disable", fd, errno, +			safe_strerror(errno)); +		close(fd); +		return PIM_SOCK_ERR_LOOP; +	} + +	memset(&mreq, 0, sizeof(mreq));  #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX -  mreq.imr_ifindex = ifp->ifindex; +	mreq.imr_ifindex = ifp->ifindex;  #else -  /* -   * I am not sure what to do here yet for *BSD -   */ -  //mreq.imr_interface = ifindex; +/* + * I am not sure what to do here yet for *BSD + */ +// mreq.imr_interface = ifindex;  #endif -  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, -		 (void *) &mreq, sizeof(mreq))) { -    zlog_warn("Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", -	      fd, errno, safe_strerror(errno)); -    close(fd); -    return PIM_SOCK_ERR_IFACE; -  } - -  if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) -      zlog_warn("%s: Failure to set buffer size to %d", -		__PRETTY_FUNCTION__, rcvbuf); - -  { -    long flags; - -    flags = fcntl(fd, F_GETFL, 0); -    if (flags < 0) { -      zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", -		fd, errno, safe_strerror(errno)); -      close(fd); -      return PIM_SOCK_ERR_NONBLOCK_GETFL; -    } - -    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { -      zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", -		fd, errno, safe_strerror(errno)); -      close(fd); -      return PIM_SOCK_ERR_NONBLOCK_SETFL; -    } -  } - -  return fd; +	if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreq, +		       sizeof(mreq))) { +		zlog_warn( +			"Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", +			fd, errno, safe_strerror(errno)); +		close(fd); +		return PIM_SOCK_ERR_IFACE; +	} + +	if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) +		zlog_warn("%s: Failure to set buffer size to %d", +			  __PRETTY_FUNCTION__, rcvbuf); + +	{ +		long flags; + +		flags = fcntl(fd, F_GETFL, 0); +		if (flags < 0) { +			zlog_warn( +				"Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", +				fd, errno, safe_strerror(errno)); +			close(fd); +			return PIM_SOCK_ERR_NONBLOCK_GETFL; +		} + +		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { +			zlog_warn( +				"Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", +				fd, errno, safe_strerror(errno)); +			close(fd); +			return PIM_SOCK_ERR_NONBLOCK_SETFL; +		} +	} + +	return fd;  } -int pim_socket_join(int fd, struct in_addr group, -		    struct in_addr ifaddr, ifindex_t ifindex) +int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr, +		    ifindex_t ifindex)  { -  int ret; +	int ret;  #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX -  struct ip_mreqn opt; +	struct ip_mreqn opt;  #else -  struct ip_mreq opt; +	struct ip_mreq opt;  #endif -  opt.imr_multiaddr = group; +	opt.imr_multiaddr = group;  #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX -  opt.imr_address   = ifaddr; -  opt.imr_ifindex   = ifindex; +	opt.imr_address = ifaddr; +	opt.imr_ifindex = ifindex;  #else -  opt.imr_interface = ifaddr; +	opt.imr_interface = ifaddr;  #endif -  ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt)); -  if (ret) { -    char group_str[INET_ADDRSTRLEN]; -    char ifaddr_str[INET_ADDRSTRLEN]; -    if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) -      sprintf(group_str, "<group?>"); -    if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) -      sprintf(ifaddr_str, "<ifaddr?>"); - -    zlog_err("Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s", -	     fd, group_str, ifaddr_str, errno, safe_strerror(errno)); -    return ret; -  } - -  if (PIM_DEBUG_TRACE) { -    char group_str[INET_ADDRSTRLEN]; -    char ifaddr_str[INET_ADDRSTRLEN]; -    if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) -      sprintf(group_str, "<group?>"); -    if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) -      sprintf(ifaddr_str, "<ifaddr?>"); - -    zlog_debug("Socket fd=%d joined group %s on interface address %s", -	       fd, group_str, ifaddr_str); -  } - -  return ret; +	ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt)); +	if (ret) { +		char group_str[INET_ADDRSTRLEN]; +		char ifaddr_str[INET_ADDRSTRLEN]; +		if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str))) +			sprintf(group_str, "<group?>"); +		if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str, +			       sizeof(ifaddr_str))) +			sprintf(ifaddr_str, "<ifaddr?>"); + +		zlog_err( +			"Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s", +			fd, group_str, ifaddr_str, errno, safe_strerror(errno)); +		return ret; +	} + +	if (PIM_DEBUG_TRACE) { +		char group_str[INET_ADDRSTRLEN]; +		char ifaddr_str[INET_ADDRSTRLEN]; +		if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str))) +			sprintf(group_str, "<group?>"); +		if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str, +			       sizeof(ifaddr_str))) +			sprintf(ifaddr_str, "<ifaddr?>"); + +		zlog_debug( +			"Socket fd=%d joined group %s on interface address %s", +			fd, group_str, ifaddr_str); +	} + +	return ret;  } -int pim_socket_join_source(int fd, ifindex_t ifindex, -			   struct in_addr group_addr, -			   struct in_addr source_addr, -			   const char *ifname) +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, +			   struct in_addr source_addr, const char *ifname)  { -  if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { -    char group_str[INET_ADDRSTRLEN]; -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str)); -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", -	      __PRETTY_FUNCTION__, -	      fd, group_str, source_str, ifindex, ifname, -	      errno, safe_strerror(errno)); -    return -1; -  } - -  return 0; +	if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { +		char group_str[INET_ADDRSTRLEN]; +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<grp?>", group_addr, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", +			__PRETTY_FUNCTION__, fd, group_str, source_str, ifindex, +			ifname, errno, safe_strerror(errno)); +		return -1; +	} + +	return 0;  }  int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, @@ -335,117 +348,121 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,  			  struct sockaddr_in *to, socklen_t *tolen,  			  ifindex_t *ifindex)  { -  struct msghdr msgh; -  struct cmsghdr *cmsg; -  struct iovec iov; -  char cbuf[1000]; -  int err; - -  /* -   * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port. -   * Use getsockname() to get sin_port. -   */ -  if (to) { -    struct sockaddr_in si; -    socklen_t si_len = sizeof(si); - -    memset (&si, 0, sizeof (si)); -    to->sin_family = AF_INET; - -    pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len); - -    to->sin_port = si.sin_port; -    to->sin_addr = si.sin_addr; - -    if (tolen)  -      *tolen = sizeof(si); -  } - -  memset(&msgh, 0, sizeof(struct msghdr)); -  iov.iov_base = buf; -  iov.iov_len  = len; -  msgh.msg_control = cbuf; -  msgh.msg_controllen = sizeof(cbuf); -  msgh.msg_name = from; -  msgh.msg_namelen = fromlen ? *fromlen : 0; -  msgh.msg_iov  = &iov; -  msgh.msg_iovlen = 1; -  msgh.msg_flags = 0; - -  err = recvmsg(fd, &msgh, 0); -  if (err < 0) -    return err; - -  if (fromlen) -    *fromlen = msgh.msg_namelen; - -  for (cmsg = CMSG_FIRSTHDR(&msgh); -       cmsg != NULL; -       cmsg = CMSG_NXTHDR(&msgh,cmsg)) { +	struct msghdr msgh; +	struct cmsghdr *cmsg; +	struct iovec iov; +	char cbuf[1000]; +	int err; + +	/* +	 * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port. +	 * Use getsockname() to get sin_port. +	 */ +	if (to) { +		struct sockaddr_in si; +		socklen_t si_len = sizeof(si); + +		memset(&si, 0, sizeof(si)); +		to->sin_family = AF_INET; + +		pim_socket_getsockname(fd, (struct sockaddr *)&si, &si_len); + +		to->sin_port = si.sin_port; +		to->sin_addr = si.sin_addr; + +		if (tolen) +			*tolen = sizeof(si); +	} + +	memset(&msgh, 0, sizeof(struct msghdr)); +	iov.iov_base = buf; +	iov.iov_len = len; +	msgh.msg_control = cbuf; +	msgh.msg_controllen = sizeof(cbuf); +	msgh.msg_name = from; +	msgh.msg_namelen = fromlen ? *fromlen : 0; +	msgh.msg_iov = &iov; +	msgh.msg_iovlen = 1; +	msgh.msg_flags = 0; + +	err = recvmsg(fd, &msgh, 0); +	if (err < 0) +		return err; + +	if (fromlen) +		*fromlen = msgh.msg_namelen; + +	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; +	     cmsg = CMSG_NXTHDR(&msgh, cmsg)) {  #ifdef HAVE_IP_PKTINFO -    if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_PKTINFO)) { -      struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg); -      if (to) -	((struct sockaddr_in *) to)->sin_addr = i->ipi_addr; -      if (tolen) -	*tolen = sizeof(struct sockaddr_in); -      if (ifindex) -	*ifindex = i->ipi_ifindex; - -      break; -    } +		if ((cmsg->cmsg_level == IPPROTO_IP) +		    && (cmsg->cmsg_type == IP_PKTINFO)) { +			struct in_pktinfo *i = +				(struct in_pktinfo *)CMSG_DATA(cmsg); +			if (to) +				((struct sockaddr_in *)to)->sin_addr = +					i->ipi_addr; +			if (tolen) +				*tolen = sizeof(struct sockaddr_in); +			if (ifindex) +				*ifindex = i->ipi_ifindex; + +			break; +		}  #endif  #ifdef HAVE_IP_RECVDSTADDR -    if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) { -      struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg); -      if (to) -	((struct sockaddr_in *) to)->sin_addr = *i; -      if (tolen) -	*tolen = sizeof(struct sockaddr_in); - -      break; -    } +		if ((cmsg->cmsg_level == IPPROTO_IP) +		    && (cmsg->cmsg_type == IP_RECVDSTADDR)) { +			struct in_addr *i = (struct in_addr *)CMSG_DATA(cmsg); +			if (to) +				((struct sockaddr_in *)to)->sin_addr = *i; +			if (tolen) +				*tolen = sizeof(struct sockaddr_in); + +			break; +		}  #endif  #if defined(HAVE_IP_RECVIF) && defined(CMSG_IFINDEX) -      if (cmsg->cmsg_type == IP_RECVIF) -	if (ifindex) -	  *ifindex = CMSG_IFINDEX(cmsg); +		if (cmsg->cmsg_type == IP_RECVIF) +			if (ifindex) +				*ifindex = CMSG_IFINDEX(cmsg);  #endif -  } /* for (cmsg) */ +	} /* for (cmsg) */ -  return err; /* len */ +	return err; /* len */  }  int pim_socket_mcastloop_get(int fd)  { -  int loop; -  socklen_t loop_len = sizeof(loop); -   -  if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, -		 &loop, &loop_len)) { -    int e = errno; -    zlog_warn("Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s", -	      fd, errno, safe_strerror(errno)); -    errno = e; -    return PIM_SOCK_ERR_LOOP; -  } -   -  return loop; +	int loop; +	socklen_t loop_len = sizeof(loop); + +	if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, &loop_len)) { +		int e = errno; +		zlog_warn( +			"Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s", +			fd, errno, safe_strerror(errno)); +		errno = e; +		return PIM_SOCK_ERR_LOOP; +	} + +	return loop;  }  int pim_socket_getsockname(int fd, struct sockaddr *name, socklen_t *namelen)  { -  if (getsockname(fd, name, namelen)) { -    int e = errno; -    zlog_warn("Could not get Socket Name for socket fd=%d: errno=%d: %s", -	      fd, errno, safe_strerror(errno)); -    errno = e; -    return PIM_SOCK_ERR_NAME; -  } - -  return PIM_SOCK_ERR_NONE; +	if (getsockname(fd, name, namelen)) { +		int e = errno; +		zlog_warn( +			"Could not get Socket Name for socket fd=%d: errno=%d: %s", +			fd, errno, safe_strerror(errno)); +		errno = e; +		return PIM_SOCK_ERR_NAME; +	} + +	return PIM_SOCK_ERR_NONE;  } diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index 9fb64677c8..aa46cd6200 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -35,16 +35,15 @@  #define PIM_SOCK_ERR_NAME    (-10) /* Socket name (getsockname) */  #define PIM_SOCK_ERR_BIND    (-11) /* Can't bind to interface */ -int pim_socket_bind (int fd, struct interface *ifp); -int pim_socket_ip_hdr (int fd); +int pim_socket_bind(int fd, struct interface *ifp); +int pim_socket_ip_hdr(int fd);  int pim_socket_raw(int protocol); -int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, u_char loop); -int pim_socket_join(int fd, struct in_addr group, -		    struct in_addr ifaddr, ifindex_t ifindex); -int pim_socket_join_source(int fd, ifindex_t ifindex, -			   struct in_addr group_addr, -			   struct in_addr source_addr, -			   const char *ifname); +int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, +		     u_char loop); +int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr, +		    ifindex_t ifindex); +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, +			   struct in_addr source_addr, const char *ifname);  int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,  			  struct sockaddr_in *from, socklen_t *fromlen,  			  struct sockaddr_in *to, socklen_t *tolen, diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c index d4f88ec2c1..3046e94299 100644 --- a/pimd/pim_ssm.c +++ b/pimd/pim_ssm.c @@ -29,129 +29,119 @@  #include "pim_ssm.h"  #include "pim_zebra.h" -static void -pim_ssm_range_reevaluate (void) +static void pim_ssm_range_reevaluate(void)  { -  /* 1. Setup register state for (S,G) entries if G has changed from SSM to -   *    ASM. -   * 2. check existing (*,G) IGMP registrations to see if they are -   * still ASM. if they are now SSM delete them. -   * 3. Allow channel setup for IGMP (*,G) members if G is now ASM -   * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an -   * unnecessary sladge hammer and may not be particularly useful as it is -   * likely the SPT switchover has already happened for flows along such RPTs. -   * As for the RPT states it seems that the best thing to do is let them age -   * out gracefully. As long as the FHR and LHR do the right thing RPTs will -   * disappear in time for SSM groups. -   */ -  pim_upstream_register_reevaluate (); -  igmp_source_forward_reevaluate_all (); +	/* 1. Setup register state for (S,G) entries if G has changed from SSM +	 * to +	 *    ASM. +	 * 2. check existing (*,G) IGMP registrations to see if they are +	 * still ASM. if they are now SSM delete them. +	 * 3. Allow channel setup for IGMP (*,G) members if G is now ASM +	 * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an +	 * unnecessary sladge hammer and may not be particularly useful as it is +	 * likely the SPT switchover has already happened for flows along such +	 * RPTs. +	 * As for the RPT states it seems that the best thing to do is let them +	 * age +	 * out gracefully. As long as the FHR and LHR do the right thing RPTs +	 * will +	 * disappear in time for SSM groups. +	 */ +	pim_upstream_register_reevaluate(); +	igmp_source_forward_reevaluate_all();  } -void -pim_ssm_prefix_list_update (struct prefix_list *plist) +void pim_ssm_prefix_list_update(struct prefix_list *plist)  { -  struct pim_ssm *ssm = pimg->ssm_info; +	struct pim_ssm *ssm = pimg->ssm_info; -  if (!ssm->plist_name || strcmp (ssm->plist_name, prefix_list_name (plist))) -    { -      /* not ours */ -      return; -    } +	if (!ssm->plist_name +	    || strcmp(ssm->plist_name, prefix_list_name(plist))) { +		/* not ours */ +		return; +	} -  pim_ssm_range_reevaluate (); +	pim_ssm_range_reevaluate();  } -static int -pim_is_grp_standard_ssm (struct prefix *group) +static int pim_is_grp_standard_ssm(struct prefix *group)  { -  static int first = 1; -  static struct prefix group_ssm; +	static int first = 1; +	static struct prefix group_ssm; -  if (first) -    { -      str2prefix (PIM_SSM_STANDARD_RANGE, &group_ssm); -      first = 0; -    } +	if (first) { +		str2prefix(PIM_SSM_STANDARD_RANGE, &group_ssm); +		first = 0; +	} -  return prefix_match (&group_ssm, group); +	return prefix_match(&group_ssm, group);  } -int -pim_is_grp_ssm (struct in_addr group_addr) +int pim_is_grp_ssm(struct in_addr group_addr)  { -  struct pim_ssm *ssm; -  struct prefix group; -  struct prefix_list *plist; - -  memset (&group, 0, sizeof (group)); -  group.family = AF_INET; -  group.u.prefix4 = group_addr; -  group.prefixlen = 32; - -  ssm = pimg->ssm_info; -  if (!ssm->plist_name) -    { -      return pim_is_grp_standard_ssm (&group); -    } - -  plist = prefix_list_lookup (AFI_IP, ssm->plist_name); -  if (!plist) -    return 0; - -  return (prefix_list_apply (plist, &group) == PREFIX_PERMIT); +	struct pim_ssm *ssm; +	struct prefix group; +	struct prefix_list *plist; + +	memset(&group, 0, sizeof(group)); +	group.family = AF_INET; +	group.u.prefix4 = group_addr; +	group.prefixlen = 32; + +	ssm = pimg->ssm_info; +	if (!ssm->plist_name) { +		return pim_is_grp_standard_ssm(&group); +	} + +	plist = prefix_list_lookup(AFI_IP, ssm->plist_name); +	if (!plist) +		return 0; + +	return (prefix_list_apply(plist, &group) == PREFIX_PERMIT);  } -int -pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name) +int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name)  { -  struct pim_ssm *ssm; -  int change = 0; - -  if (vrf_id != VRF_DEFAULT) -    return PIM_SSM_ERR_NO_VRF; - -  ssm = pimg->ssm_info; -  if (plist_name) -    { -      if (ssm->plist_name) -        { -          if (!strcmp (ssm->plist_name, plist_name)) -            return PIM_SSM_ERR_DUP; -          XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); -        } -      ssm->plist_name = XSTRDUP (MTYPE_PIM_FILTER_NAME, plist_name); -      change = 1; -    } -  else -    { -      if (ssm->plist_name) -        { -          change = 1; -          XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); -        } -    } - -  if (change) -    pim_ssm_range_reevaluate (); - -  return PIM_SSM_ERR_NONE; +	struct pim_ssm *ssm; +	int change = 0; + +	if (vrf_id != VRF_DEFAULT) +		return PIM_SSM_ERR_NO_VRF; + +	ssm = pimg->ssm_info; +	if (plist_name) { +		if (ssm->plist_name) { +			if (!strcmp(ssm->plist_name, plist_name)) +				return PIM_SSM_ERR_DUP; +			XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); +		} +		ssm->plist_name = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist_name); +		change = 1; +	} else { +		if (ssm->plist_name) { +			change = 1; +			XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); +		} +	} + +	if (change) +		pim_ssm_range_reevaluate(); + +	return PIM_SSM_ERR_NONE;  } -void * -pim_ssm_init (vrf_id_t vrf_id) +void *pim_ssm_init(vrf_id_t vrf_id)  { -  struct pim_ssm *ssm; +	struct pim_ssm *ssm; -  ssm = XCALLOC (MTYPE_PIM_SSM_INFO, sizeof (*ssm)); -  ssm->vrf_id = vrf_id; +	ssm = XCALLOC(MTYPE_PIM_SSM_INFO, sizeof(*ssm)); +	ssm->vrf_id = vrf_id; -  return ssm; +	return ssm;  } -void -pim_ssm_terminate (struct pim_ssm *ssm) +void pim_ssm_terminate(struct pim_ssm *ssm)  { -  if (ssm && ssm->plist_name) -    XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); +	if (ssm && ssm->plist_name) +		XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);  } diff --git a/pimd/pim_ssm.h b/pimd/pim_ssm.h index fe337be8f1..9e89d0c80c 100644 --- a/pimd/pim_ssm.h +++ b/pimd/pim_ssm.h @@ -22,22 +22,20 @@  #define PIM_SSM_STANDARD_RANGE "232.0.0.0/8"  /* SSM error codes */ -enum pim_ssm_err -{ -  PIM_SSM_ERR_NONE = 0, -  PIM_SSM_ERR_NO_VRF = -1, -  PIM_SSM_ERR_DUP = -2, +enum pim_ssm_err { +	PIM_SSM_ERR_NONE = 0, +	PIM_SSM_ERR_NO_VRF = -1, +	PIM_SSM_ERR_DUP = -2,  }; -struct pim_ssm -{ -  vrf_id_t vrf_id; -  char *plist_name; /* prefix list of group ranges */ +struct pim_ssm { +	vrf_id_t vrf_id; +	char *plist_name; /* prefix list of group ranges */  }; -void pim_ssm_prefix_list_update (struct prefix_list *plist); -int pim_is_grp_ssm (struct in_addr group_addr); -int pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name); -void *pim_ssm_init (vrf_id_t vrf_id); -void pim_ssm_terminate (struct pim_ssm *ssm); +void pim_ssm_prefix_list_update(struct prefix_list *plist); +int pim_is_grp_ssm(struct in_addr group_addr); +int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name); +void *pim_ssm_init(vrf_id_t vrf_id); +void pim_ssm_terminate(struct pim_ssm *ssm);  #endif diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index dd92ff1b28..406183db86 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -30,402 +30,423 @@  #include "pim_time.h"  #include "pim_sock.h" -static const char * const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; +static const char *const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; -enum { -  PIM_SSMPINGD_REQUEST = 'Q', -  PIM_SSMPINGD_REPLY   = 'A' -}; +enum { PIM_SSMPINGD_REQUEST = 'Q', PIM_SSMPINGD_REPLY = 'A' };  static void ssmpingd_read_on(struct ssmpingd_sock *ss);  void pim_ssmpingd_init()  { -  int result; +	int result; -  zassert(!qpim_ssmpingd_list); +	zassert(!qpim_ssmpingd_list); -  result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, &qpim_ssmpingd_group_addr); -   -  zassert(result > 0); +	result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, +			   &qpim_ssmpingd_group_addr); + +	zassert(result > 0);  }  void pim_ssmpingd_destroy()  { -  if (qpim_ssmpingd_list) { -    list_free(qpim_ssmpingd_list); -    qpim_ssmpingd_list = 0; -  } +	if (qpim_ssmpingd_list) { +		list_free(qpim_ssmpingd_list); +		qpim_ssmpingd_list = 0; +	}  }  static struct ssmpingd_sock *ssmpingd_find(struct in_addr source_addr)  { -  struct listnode      *node; -  struct ssmpingd_sock *ss; +	struct listnode *node; +	struct ssmpingd_sock *ss; -  if (!qpim_ssmpingd_list) -    return 0; +	if (!qpim_ssmpingd_list) +		return 0; -  for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) -    if (source_addr.s_addr == ss->source_addr.s_addr) -      return ss; +	for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) +		if (source_addr.s_addr == ss->source_addr.s_addr) +			return ss; -  return 0; +	return 0;  }  static void ssmpingd_free(struct ssmpingd_sock *ss)  { -  XFREE(MTYPE_PIM_SSMPINGD, ss); +	XFREE(MTYPE_PIM_SSMPINGD, ss);  }  static int ssmpingd_socket(struct in_addr addr, int port, int mttl)  { -  struct sockaddr_in sockaddr; -  int fd; - -  fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); -  if (fd < 0) { -    zlog_err("%s: could not create socket: errno=%d: %s", -	     __PRETTY_FUNCTION__, errno, safe_strerror(errno)); -    return -1; -  } - -  sockaddr.sin_family = AF_INET; -  sockaddr.sin_addr   = addr; -  sockaddr.sin_port   = htons(port); - -  if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { -    char addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -    zlog_warn("%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", -	      __PRETTY_FUNCTION__, -	      fd, addr_str, port, sizeof(sockaddr), -	      errno, safe_strerror(errno)); -    close(fd); -    return -1; -  } - -  /* Needed to obtain destination address from recvmsg() */ -  { +	struct sockaddr_in sockaddr; +	int fd; + +	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +	if (fd < 0) { +		zlog_err("%s: could not create socket: errno=%d: %s", +			 __PRETTY_FUNCTION__, errno, safe_strerror(errno)); +		return -1; +	} + +	sockaddr.sin_family = AF_INET; +	sockaddr.sin_addr = addr; +	sockaddr.sin_port = htons(port); + +	if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_warn( +			"%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", +			__PRETTY_FUNCTION__, fd, addr_str, port, +			sizeof(sockaddr), errno, safe_strerror(errno)); +		close(fd); +		return -1; +	} + +	/* Needed to obtain destination address from recvmsg() */ +	{  #if defined(HAVE_IP_PKTINFO) -    /* Linux and Solaris IP_PKTINFO */ -    int opt = 1; -    if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { -      zlog_warn("%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", -		__PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); -    } +		/* Linux and Solaris IP_PKTINFO */ +		int opt = 1; +		if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { +			zlog_warn( +				"%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", +				__PRETTY_FUNCTION__, fd, errno, +				safe_strerror(errno)); +		}  #elif defined(HAVE_IP_RECVDSTADDR) -    /* BSD IP_RECVDSTADDR */ -    int opt = 1; -    if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) { -      zlog_warn("%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", -		__PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); -    } +		/* BSD IP_RECVDSTADDR */ +		int opt = 1; +		if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, +			       sizeof(opt))) { +			zlog_warn( +				"%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", +				__PRETTY_FUNCTION__, fd, errno, +				safe_strerror(errno)); +		}  #else -    zlog_err("%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", -	     __FILE__, __PRETTY_FUNCTION__); -    close(fd); -    return -1; +		zlog_err( +			"%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", +			__FILE__, __PRETTY_FUNCTION__); +		close(fd); +		return -1;  #endif -  } -   -  { -    int reuse = 1; -    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, -		   (void *) &reuse, sizeof(reuse))) { -      zlog_warn("%s: could not set Reuse Address Option on socket fd=%d: errno=%d: %s", -		__PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); -      close(fd); -      return -1; -    } -  } - -  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, -		 (void *) &mttl, sizeof(mttl))) { -    zlog_warn("%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", -	      __PRETTY_FUNCTION__, mttl, fd, errno, safe_strerror(errno)); -    close(fd); -    return -1; -  } - -  if (setsockopt_ipv4_multicast_loop (fd, 0)) { -    zlog_warn("%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", -	      __PRETTY_FUNCTION__, -	      fd, errno, safe_strerror(errno)); -    close(fd); -    return PIM_SOCK_ERR_LOOP; -  } - -  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, -		 (void *) &addr, sizeof(addr))) { -    zlog_warn("%s: could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", -	      __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); -    close(fd); -    return -1; -  } - -  { -    long flags; - -    flags = fcntl(fd, F_GETFL, 0); -    if (flags < 0) { -      zlog_warn("%s: could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", -		__PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); -      close(fd); -      return -1; -    } - -    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { -      zlog_warn("%s: could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", -		__PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); -      close(fd); -      return -1; -    } -  } - -  return fd; +	} + +	{ +		int reuse = 1; +		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, +			       sizeof(reuse))) { +			zlog_warn( +				"%s: could not set Reuse Address Option on socket fd=%d: errno=%d: %s", +				__PRETTY_FUNCTION__, fd, errno, +				safe_strerror(errno)); +			close(fd); +			return -1; +		} +	} + +	if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&mttl, +		       sizeof(mttl))) { +		zlog_warn( +			"%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", +			__PRETTY_FUNCTION__, mttl, fd, errno, +			safe_strerror(errno)); +		close(fd); +		return -1; +	} + +	if (setsockopt_ipv4_multicast_loop(fd, 0)) { +		zlog_warn( +			"%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", +			__PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); +		close(fd); +		return PIM_SOCK_ERR_LOOP; +	} + +	if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)&addr, +		       sizeof(addr))) { +		zlog_warn( +			"%s: could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", +			__PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); +		close(fd); +		return -1; +	} + +	{ +		long flags; + +		flags = fcntl(fd, F_GETFL, 0); +		if (flags < 0) { +			zlog_warn( +				"%s: could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", +				__PRETTY_FUNCTION__, fd, errno, +				safe_strerror(errno)); +			close(fd); +			return -1; +		} + +		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { +			zlog_warn( +				"%s: could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", +				__PRETTY_FUNCTION__, fd, errno, +				safe_strerror(errno)); +			close(fd); +			return -1; +		} +	} + +	return fd;  }  static void ssmpingd_delete(struct ssmpingd_sock *ss)  { -  zassert(ss); -  zassert(qpim_ssmpingd_list); - -  THREAD_OFF(ss->t_sock_read); - -  if (close(ss->sock_fd)) { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", -	      __PRETTY_FUNCTION__, -	      ss->sock_fd, source_str, errno, safe_strerror(errno)); -    /* warning only */ -  } - -  listnode_delete(qpim_ssmpingd_list, ss); -  ssmpingd_free(ss); +	zassert(ss); +	zassert(qpim_ssmpingd_list); + +	THREAD_OFF(ss->t_sock_read); + +	if (close(ss->sock_fd)) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", ss->source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", +			__PRETTY_FUNCTION__, ss->sock_fd, source_str, errno, +			safe_strerror(errno)); +		/* warning only */ +	} + +	listnode_delete(qpim_ssmpingd_list, ss); +	ssmpingd_free(ss);  } -static void ssmpingd_sendto(struct ssmpingd_sock *ss, -			    const uint8_t *buf, -			    int len, -			    struct sockaddr_in to) +static void ssmpingd_sendto(struct ssmpingd_sock *ss, const uint8_t *buf, +			    int len, struct sockaddr_in to)  { -  socklen_t tolen = sizeof(to); -  int sent; - -  sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, -                (struct sockaddr *)&to, tolen); -  if (sent != len) { -    char to_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); -    if (sent < 0) { -      zlog_warn("%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", -		__PRETTY_FUNCTION__, -		to_str, ntohs(to.sin_port), ss->sock_fd, len, -		errno, safe_strerror(errno)); -    } -    else { -      zlog_warn("%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", -		__PRETTY_FUNCTION__, -		to_str, ntohs(to.sin_port), ss->sock_fd, -		len, sent); -    } -  } +	socklen_t tolen = sizeof(to); +	int sent; + +	sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, +		      (struct sockaddr *)&to, tolen); +	if (sent != len) { +		char to_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); +		if (sent < 0) { +			zlog_warn( +				"%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", +				__PRETTY_FUNCTION__, to_str, ntohs(to.sin_port), +				ss->sock_fd, len, errno, safe_strerror(errno)); +		} else { +			zlog_warn( +				"%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", +				__PRETTY_FUNCTION__, to_str, ntohs(to.sin_port), +				ss->sock_fd, len, sent); +		} +	}  }  static int ssmpingd_read_msg(struct ssmpingd_sock *ss)  { -  struct interface *ifp; -  struct sockaddr_in from; -  struct sockaddr_in to; -  socklen_t fromlen = sizeof(from); -  socklen_t tolen = sizeof(to); -  ifindex_t ifindex = -1; -  uint8_t buf[1000]; -  int len; - -  ++ss->requests; - -  len = pim_socket_recvfromto(ss->sock_fd, buf, sizeof(buf), -			      &from, &fromlen, -			      &to, &tolen, -			      &ifindex); -  if (len < 0) { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: failure receiving ssmping for source %s on fd=%d: errno=%d: %s", -	      __PRETTY_FUNCTION__, source_str, ss->sock_fd, errno, safe_strerror(errno)); -    return -1; -  } - -  ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - -  if (buf[0] != PIM_SSMPINGD_REQUEST) { -    char source_str[INET_ADDRSTRLEN]; -    char from_str[INET_ADDRSTRLEN]; -    char to_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); -    pim_inet4_dump("<from?>", from.sin_addr, from_str, sizeof(from_str)); -    pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); -    zlog_warn("%s: bad ssmping type=%d from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", -	      __PRETTY_FUNCTION__, -	      buf[0], -	      from_str, ntohs(from.sin_port), -	      to_str, ntohs(to.sin_port), -	      ifp ? ifp->name : "<iface?>", -	      ifindex, ss->sock_fd, -	      source_str); -    return 0; -  } - -  if (PIM_DEBUG_SSMPINGD) { -    char source_str[INET_ADDRSTRLEN]; -    char from_str[INET_ADDRSTRLEN]; -    char to_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); -    pim_inet4_dump("<from?>", from.sin_addr, from_str, sizeof(from_str)); -    pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); -    zlog_debug("%s: recv ssmping from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", -	       __PRETTY_FUNCTION__, -	       from_str, ntohs(from.sin_port), -	       to_str, ntohs(to.sin_port), -	       ifp ? ifp->name : "<iface?>", -	       ifindex, ss->sock_fd, -	       source_str); -  } - -  buf[0] = PIM_SSMPINGD_REPLY; - -  /* unicast reply */ -  ssmpingd_sendto(ss, buf, len, from); - -  /* multicast reply */ -  from.sin_addr = qpim_ssmpingd_group_addr; -  ssmpingd_sendto(ss, buf, len, from); - -  return 0; +	struct interface *ifp; +	struct sockaddr_in from; +	struct sockaddr_in to; +	socklen_t fromlen = sizeof(from); +	socklen_t tolen = sizeof(to); +	ifindex_t ifindex = -1; +	uint8_t buf[1000]; +	int len; + +	++ss->requests; + +	len = pim_socket_recvfromto(ss->sock_fd, buf, sizeof(buf), &from, +				    &fromlen, &to, &tolen, &ifindex); +	if (len < 0) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", ss->source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn( +			"%s: failure receiving ssmping for source %s on fd=%d: errno=%d: %s", +			__PRETTY_FUNCTION__, source_str, ss->sock_fd, errno, +			safe_strerror(errno)); +		return -1; +	} + +	ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + +	if (buf[0] != PIM_SSMPINGD_REQUEST) { +		char source_str[INET_ADDRSTRLEN]; +		char from_str[INET_ADDRSTRLEN]; +		char to_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", ss->source_addr, source_str, +			       sizeof(source_str)); +		pim_inet4_dump("<from?>", from.sin_addr, from_str, +			       sizeof(from_str)); +		pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); +		zlog_warn( +			"%s: bad ssmping type=%d from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", +			__PRETTY_FUNCTION__, buf[0], from_str, +			ntohs(from.sin_port), to_str, ntohs(to.sin_port), +			ifp ? ifp->name : "<iface?>", ifindex, ss->sock_fd, +			source_str); +		return 0; +	} + +	if (PIM_DEBUG_SSMPINGD) { +		char source_str[INET_ADDRSTRLEN]; +		char from_str[INET_ADDRSTRLEN]; +		char to_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", ss->source_addr, source_str, +			       sizeof(source_str)); +		pim_inet4_dump("<from?>", from.sin_addr, from_str, +			       sizeof(from_str)); +		pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str)); +		zlog_debug( +			"%s: recv ssmping from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", +			__PRETTY_FUNCTION__, from_str, ntohs(from.sin_port), +			to_str, ntohs(to.sin_port), +			ifp ? ifp->name : "<iface?>", ifindex, ss->sock_fd, +			source_str); +	} + +	buf[0] = PIM_SSMPINGD_REPLY; + +	/* unicast reply */ +	ssmpingd_sendto(ss, buf, len, from); + +	/* multicast reply */ +	from.sin_addr = qpim_ssmpingd_group_addr; +	ssmpingd_sendto(ss, buf, len, from); + +	return 0;  }  static int ssmpingd_sock_read(struct thread *t)  { -  struct ssmpingd_sock *ss; -  int result; +	struct ssmpingd_sock *ss; +	int result; -  ss = THREAD_ARG(t); +	ss = THREAD_ARG(t); -  result = ssmpingd_read_msg(ss); +	result = ssmpingd_read_msg(ss); -  /* Keep reading */ -  ssmpingd_read_on(ss); +	/* Keep reading */ +	ssmpingd_read_on(ss); -  return result; +	return result;  }  static void ssmpingd_read_on(struct ssmpingd_sock *ss)  { -  thread_add_read(master, ssmpingd_sock_read, ss, ss->sock_fd, -                  &ss->t_sock_read); +	thread_add_read(master, ssmpingd_sock_read, ss, ss->sock_fd, +			&ss->t_sock_read);  }  static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr)  { -  struct ssmpingd_sock *ss; -  int sock_fd; - -  if (!qpim_ssmpingd_list) { -    qpim_ssmpingd_list = list_new(); -    if (!qpim_ssmpingd_list) { -      zlog_err("%s %s: failure: qpim_ssmpingd_list=list_new()", -	       __FILE__, __PRETTY_FUNCTION__); -      return 0; -    } -    qpim_ssmpingd_list->del = (void (*)(void *)) ssmpingd_free; -  } - -  sock_fd = ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); -  if (sock_fd < 0) { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: ssmpingd_socket() failure for source %s", -	      __PRETTY_FUNCTION__, source_str); -    return 0; -  } - -  ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); -  if (!ss) { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", -	     __PRETTY_FUNCTION__, -	     sizeof(*ss), source_str); -    close(sock_fd); -    return 0; -  } - -  ss->sock_fd     = sock_fd; -  ss->t_sock_read = NULL; -  ss->source_addr = source_addr; -  ss->creation    = pim_time_monotonic_sec(); -  ss->requests    = 0; - -  listnode_add(qpim_ssmpingd_list, ss); - -  ssmpingd_read_on(ss); - -  return ss; +	struct ssmpingd_sock *ss; +	int sock_fd; + +	if (!qpim_ssmpingd_list) { +		qpim_ssmpingd_list = list_new(); +		if (!qpim_ssmpingd_list) { +			zlog_err( +				"%s %s: failure: qpim_ssmpingd_list=list_new()", +				__FILE__, __PRETTY_FUNCTION__); +			return 0; +		} +		qpim_ssmpingd_list->del = (void (*)(void *))ssmpingd_free; +	} + +	sock_fd = +		ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); +	if (sock_fd < 0) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn("%s: ssmpingd_socket() failure for source %s", +			  __PRETTY_FUNCTION__, source_str); +		return 0; +	} + +	ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); +	if (!ss) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", +			 __PRETTY_FUNCTION__, sizeof(*ss), source_str); +		close(sock_fd); +		return 0; +	} + +	ss->sock_fd = sock_fd; +	ss->t_sock_read = NULL; +	ss->source_addr = source_addr; +	ss->creation = pim_time_monotonic_sec(); +	ss->requests = 0; + +	listnode_add(qpim_ssmpingd_list, ss); + +	ssmpingd_read_on(ss); + +	return ss;  }  int pim_ssmpingd_start(struct in_addr source_addr)  { -  struct ssmpingd_sock *ss; - -  ss = ssmpingd_find(source_addr); -  if (ss) { -    /* silently ignore request to recreate entry */ -    return 0; -  } - -  { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_info("%s: starting ssmpingd for source %s", -	      __PRETTY_FUNCTION__, source_str); -  } - -  ss = ssmpingd_new(source_addr); -  if (!ss) { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: ssmpingd_new() failure for source %s", -	      __PRETTY_FUNCTION__, source_str); -    return -1; -  } - -  return 0; +	struct ssmpingd_sock *ss; + +	ss = ssmpingd_find(source_addr); +	if (ss) { +		/* silently ignore request to recreate entry */ +		return 0; +	} + +	{ +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_info("%s: starting ssmpingd for source %s", +			  __PRETTY_FUNCTION__, source_str); +	} + +	ss = ssmpingd_new(source_addr); +	if (!ss) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn("%s: ssmpingd_new() failure for source %s", +			  __PRETTY_FUNCTION__, source_str); +		return -1; +	} + +	return 0;  }  int pim_ssmpingd_stop(struct in_addr source_addr)  { -  struct ssmpingd_sock *ss; - -  ss = ssmpingd_find(source_addr); -  if (!ss) { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_warn("%s: could not find ssmpingd for source %s", -	      __PRETTY_FUNCTION__, source_str); -    return -1; -  } - -  { -    char source_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str)); -    zlog_info("%s: stopping ssmpingd for source %s", -	      __PRETTY_FUNCTION__, source_str); -  } - -  ssmpingd_delete(ss); - -  return 0; +	struct ssmpingd_sock *ss; + +	ss = ssmpingd_find(source_addr); +	if (!ss) { +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_warn("%s: could not find ssmpingd for source %s", +			  __PRETTY_FUNCTION__, source_str); +		return -1; +	} + +	{ +		char source_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", source_addr, source_str, +			       sizeof(source_str)); +		zlog_info("%s: stopping ssmpingd for source %s", +			  __PRETTY_FUNCTION__, source_str); +	} + +	ssmpingd_delete(ss); + +	return 0;  } diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h index 02aa6271ca..89fb320a76 100644 --- a/pimd/pim_ssmpingd.h +++ b/pimd/pim_ssmpingd.h @@ -27,11 +27,11 @@  #include "pim_iface.h"  struct ssmpingd_sock { -  int            sock_fd;     /* socket */ -  struct thread *t_sock_read; /* thread for reading socket */ -  struct in_addr source_addr; /* source address */ -  int64_t        creation;    /* timestamp of socket creation */ -  int64_t        requests;    /* counter */ +	int sock_fd;		    /* socket */ +	struct thread *t_sock_read; /* thread for reading socket */ +	struct in_addr source_addr; /* source address */ +	int64_t creation;	   /* timestamp of socket creation */ +	int64_t requests;	   /* counter */  };  void pim_ssmpingd_init(void); diff --git a/pimd/pim_static.c b/pimd/pim_static.c index d373581fec..7c9aca47a7 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -34,317 +34,337 @@  void pim_static_route_free(struct static_route *s_route)  { -  XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); +	XFREE(MTYPE_PIM_STATIC_ROUTE, s_route);  } -static struct static_route * static_route_alloc() +static struct static_route *static_route_alloc()  { -   struct static_route *s_route; - -   s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); -   if (!s_route) { -     zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); -     return 0; -   } -   return s_route; +	struct static_route *s_route; + +	s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); +	if (!s_route) { +		zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); +		return 0; +	} +	return s_route;  } -static struct static_route *static_route_new(unsigned int   iif, -                                             unsigned int   oif, -                                             struct in_addr group, -                                             struct in_addr source) +static struct static_route *static_route_new(unsigned int iif, unsigned int oif, +					     struct in_addr group, +					     struct in_addr source)  { -  struct static_route * s_route; -  s_route = static_route_alloc(); -  if (!s_route) { -     return 0; -  } - -  s_route->group             = group; -  s_route->source            = source; -  s_route->iif               = iif; -  s_route->oif_ttls[oif]     = 1; -  s_route->c_oil.oil_ref_count         = 1; -  s_route->c_oil.oil.mfcc_origin    = source; -  s_route->c_oil.oil.mfcc_mcastgrp  = group; -  s_route->c_oil.oil.mfcc_parent    = iif; -  s_route->c_oil.oil.mfcc_ttls[oif] = 1; -  s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); - -  return s_route; +	struct static_route *s_route; +	s_route = static_route_alloc(); +	if (!s_route) { +		return 0; +	} + +	s_route->group = group; +	s_route->source = source; +	s_route->iif = iif; +	s_route->oif_ttls[oif] = 1; +	s_route->c_oil.oil_ref_count = 1; +	s_route->c_oil.oil.mfcc_origin = source; +	s_route->c_oil.oil.mfcc_mcastgrp = group; +	s_route->c_oil.oil.mfcc_parent = iif; +	s_route->c_oil.oil.mfcc_ttls[oif] = 1; +	s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); + +	return s_route;  } -int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_add(struct interface *iif, struct interface *oif, +		   struct in_addr group, struct in_addr source)  { -   struct listnode *node = NULL; -   struct static_route *s_route = NULL; -   struct static_route *original_s_route = NULL; -   struct pim_interface *pim_iif = iif ? iif->info : NULL; -   struct pim_interface *pim_oif = oif ? oif->info : NULL; -   ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; -   ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - -   if (!iif_index || !oif_index) { -      zlog_warn("%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", -               __FILE__, __PRETTY_FUNCTION__, -               iif_index, -               oif_index); -      return -2; -   } +	struct listnode *node = NULL; +	struct static_route *s_route = NULL; +	struct static_route *original_s_route = NULL; +	struct pim_interface *pim_iif = iif ? iif->info : NULL; +	struct pim_interface *pim_oif = oif ? oif->info : NULL; +	ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; +	ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + +	if (!iif_index || !oif_index) { +		zlog_warn( +			"%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", +			__FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); +		return -2; +	}  #ifdef PIM_ENFORCE_LOOPFREE_MFC -   if (iif_index == oif_index) { -      /* looped MFC entry */ -      zlog_warn("%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", -               __FILE__, __PRETTY_FUNCTION__, -               iif_index, -               oif_index); -      return -4; -   } +	if (iif_index == oif_index) { +		/* looped MFC entry */ +		zlog_warn( +			"%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", +			__FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); +		return -4; +	}  #endif -   for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { -      if (s_route->group.s_addr == group.s_addr && -          s_route->source.s_addr == source.s_addr) { -         if (s_route->iif == iif_index && -             s_route->oif_ttls[oif_index]) { -            char gifaddr_str[INET_ADDRSTRLEN]; -            char sifaddr_str[INET_ADDRSTRLEN]; -            pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); -            pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); -            zlog_warn("%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", -                     __FILE__, __PRETTY_FUNCTION__, -                     iif_index, -                     oif_index, -                     gifaddr_str, -                     sifaddr_str); -            return -3; -         } - -         /* Ok, from here on out we will be making changes to the s_route structure, but if -          * for some reason we fail to commit these changes to the kernel, we want to be able -          * restore the state of the list. So copy the node data and if need be, we can copy -          * back if it fails. -          */ -         original_s_route = static_route_alloc(); -         if (!original_s_route) { -            return -5; -         } -         memcpy(original_s_route, s_route, sizeof(struct static_route)); - -         /* Route exists and has the same input interface, but adding a new output interface */ -         if (s_route->iif == iif_index) { -            s_route->oif_ttls[oif_index] = 1; -            s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; -            s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); -            ++s_route->c_oil.oil_ref_count; -         } else { -            /* input interface changed */ -            s_route->iif = iif_index; -            s_route->c_oil.oil.mfcc_parent = iif_index; +	for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { +		if (s_route->group.s_addr == group.s_addr +		    && s_route->source.s_addr == source.s_addr) { +			if (s_route->iif == iif_index +			    && s_route->oif_ttls[oif_index]) { +				char gifaddr_str[INET_ADDRSTRLEN]; +				char sifaddr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<ifaddr?>", group, gifaddr_str, +					       sizeof(gifaddr_str)); +				pim_inet4_dump("<ifaddr?>", source, sifaddr_str, +					       sizeof(sifaddr_str)); +				zlog_warn( +					"%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", +					__FILE__, __PRETTY_FUNCTION__, +					iif_index, oif_index, gifaddr_str, +					sifaddr_str); +				return -3; +			} + +			/* Ok, from here on out we will be making changes to the +			 * s_route structure, but if +			 * for some reason we fail to commit these changes to +			 * the kernel, we want to be able +			 * restore the state of the list. So copy the node data +			 * and if need be, we can copy +			 * back if it fails. +			 */ +			original_s_route = static_route_alloc(); +			if (!original_s_route) { +				return -5; +			} +			memcpy(original_s_route, s_route, +			       sizeof(struct static_route)); + +			/* Route exists and has the same input interface, but +			 * adding a new output interface */ +			if (s_route->iif == iif_index) { +				s_route->oif_ttls[oif_index] = 1; +				s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; +				s_route->c_oil.oif_creation[oif_index] = +					pim_time_monotonic_sec(); +				++s_route->c_oil.oil_ref_count; +			} else { +				/* input interface changed */ +				s_route->iif = iif_index; +				s_route->c_oil.oil.mfcc_parent = iif_index;  #ifdef PIM_ENFORCE_LOOPFREE_MFC -            /* check to make sure the new input was not an old output */ -            if (s_route->oif_ttls[iif_index]) { -               s_route->oif_ttls[iif_index] = 0; -               s_route->c_oil.oif_creation[iif_index] = 0; -               s_route->c_oil.oil.mfcc_ttls[iif_index] = 0; -               --s_route->c_oil.oil_ref_count; -            } +				/* check to make sure the new input was not an +				 * old output */ +				if (s_route->oif_ttls[iif_index]) { +					s_route->oif_ttls[iif_index] = 0; +					s_route->c_oil.oif_creation[iif_index] = +						0; +					s_route->c_oil.oil +						.mfcc_ttls[iif_index] = 0; +					--s_route->c_oil.oil_ref_count; +				}  #endif -            /* now add the new output, if it is new */ -            if (!s_route->oif_ttls[oif_index]) { -               s_route->oif_ttls[oif_index] = 1; -               s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); -               s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; -               ++s_route->c_oil.oil_ref_count; -            } -         } - -         break; -      } -   } - -   /* If node is null then we reached the end of the list without finding a match */ -   if (!node) { -      s_route = static_route_new(iif_index, oif_index, group, source); -      listnode_add(qpim_static_route_list, s_route); -   } - -   if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) -   { -      char gifaddr_str[INET_ADDRSTRLEN]; -      char sifaddr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); -      pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); -      zlog_warn("%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", -               __FILE__, __PRETTY_FUNCTION__, -               iif_index, -               oif_index, -               gifaddr_str, -               sifaddr_str); - -      /* Need to put s_route back to the way it was */ -      if (original_s_route) { -         memcpy(s_route, original_s_route, sizeof(struct static_route)); -      } else { -         /* we never stored off a copy, so it must have been a fresh new route */ -         listnode_delete(qpim_static_route_list, s_route); -         pim_static_route_free(s_route); -      } - -      if (original_s_route) { -         pim_static_route_free(original_s_route); -      } - -      return -1; -   } - -   /* Make sure we free the memory for the route copy if used */ -   if (original_s_route) { -      pim_static_route_free(original_s_route); -   } - -   if (PIM_DEBUG_STATIC) { -     char gifaddr_str[INET_ADDRSTRLEN]; -     char sifaddr_str[INET_ADDRSTRLEN]; -     pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); -     pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); -     zlog_debug("%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", -           __PRETTY_FUNCTION__, -           iif_index, -           oif_index, -           gifaddr_str, -           sifaddr_str); -   } - -   return 0; +				/* now add the new output, if it is new */ +				if (!s_route->oif_ttls[oif_index]) { +					s_route->oif_ttls[oif_index] = 1; +					s_route->c_oil.oif_creation[oif_index] = +						pim_time_monotonic_sec(); +					s_route->c_oil.oil +						.mfcc_ttls[oif_index] = 1; +					++s_route->c_oil.oil_ref_count; +				} +			} + +			break; +		} +	} + +	/* If node is null then we reached the end of the list without finding a +	 * match */ +	if (!node) { +		s_route = static_route_new(iif_index, oif_index, group, source); +		listnode_add(qpim_static_route_list, s_route); +	} + +	if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { +		char gifaddr_str[INET_ADDRSTRLEN]; +		char sifaddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", group, gifaddr_str, +			       sizeof(gifaddr_str)); +		pim_inet4_dump("<ifaddr?>", source, sifaddr_str, +			       sizeof(sifaddr_str)); +		zlog_warn( +			"%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", +			__FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, +			gifaddr_str, sifaddr_str); + +		/* Need to put s_route back to the way it was */ +		if (original_s_route) { +			memcpy(s_route, original_s_route, +			       sizeof(struct static_route)); +		} else { +			/* we never stored off a copy, so it must have been a +			 * fresh new route */ +			listnode_delete(qpim_static_route_list, s_route); +			pim_static_route_free(s_route); +		} + +		if (original_s_route) { +			pim_static_route_free(original_s_route); +		} + +		return -1; +	} + +	/* Make sure we free the memory for the route copy if used */ +	if (original_s_route) { +		pim_static_route_free(original_s_route); +	} + +	if (PIM_DEBUG_STATIC) { +		char gifaddr_str[INET_ADDRSTRLEN]; +		char sifaddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", group, gifaddr_str, +			       sizeof(gifaddr_str)); +		pim_inet4_dump("<ifaddr?>", source, sifaddr_str, +			       sizeof(sifaddr_str)); +		zlog_debug( +			"%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", +			__PRETTY_FUNCTION__, iif_index, oif_index, gifaddr_str, +			sifaddr_str); +	} + +	return 0;  } -int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_del(struct interface *iif, struct interface *oif, +		   struct in_addr group, struct in_addr source)  { -   struct listnode *node = NULL; -   struct listnode *nextnode = NULL; -   struct static_route *s_route = NULL; -   struct pim_interface *pim_iif = iif ? iif->info : 0; -   struct pim_interface *pim_oif = oif ? oif->info : 0; -   ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; -   ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - -   if (!iif_index || !oif_index) { -      zlog_warn("%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", -               __FILE__, __PRETTY_FUNCTION__, -               iif_index, -               oif_index); -      return -2; -   } - -   for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, s_route)) { -      if (s_route->iif == iif_index && -          s_route->group.s_addr == group.s_addr && -          s_route->source.s_addr == source.s_addr && -          s_route->oif_ttls[oif_index]) { -         s_route->oif_ttls[oif_index] = 0; -         s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; -         --s_route->c_oil.oil_ref_count; - -         /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ -         if (s_route->c_oil.oil_ref_count <= 0 ? -	     pim_mroute_del(&s_route->c_oil, __PRETTY_FUNCTION__) : pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { -	   char gifaddr_str[INET_ADDRSTRLEN]; -	   char sifaddr_str[INET_ADDRSTRLEN]; -	   pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); -	   pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); -	   zlog_warn("%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", -                     __FILE__, __PRETTY_FUNCTION__, -                     iif_index, -                     oif_index, -                     gifaddr_str, -                     sifaddr_str); - -	   s_route->oif_ttls[oif_index] = 1; -	   s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; -	   ++s_route->c_oil.oil_ref_count; - -	   return -1; -         } - -         s_route->c_oil.oif_creation[oif_index] = 0; - -         if (s_route->c_oil.oil_ref_count <= 0) { -            listnode_delete(qpim_static_route_list, s_route); -            pim_static_route_free(s_route); -         } - -         if (PIM_DEBUG_STATIC) { -           char gifaddr_str[INET_ADDRSTRLEN]; -           char sifaddr_str[INET_ADDRSTRLEN]; -           pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); -           pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); -           zlog_debug("%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", -                 __PRETTY_FUNCTION__, -                 iif_index, -                 oif_index, -                 gifaddr_str, -                 sifaddr_str); -         } - -         break; -      } -   } - -   if (!node) { -      char gifaddr_str[INET_ADDRSTRLEN]; -      char sifaddr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<ifaddr?>", group, gifaddr_str, sizeof(gifaddr_str)); -      pim_inet4_dump("<ifaddr?>", source, sifaddr_str, sizeof(sifaddr_str)); -      zlog_warn("%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", -               __FILE__, __PRETTY_FUNCTION__, -               iif_index, -               oif_index, -               gifaddr_str, -               sifaddr_str); -      return -3; -   } - -   return 0; +	struct listnode *node = NULL; +	struct listnode *nextnode = NULL; +	struct static_route *s_route = NULL; +	struct pim_interface *pim_iif = iif ? iif->info : 0; +	struct pim_interface *pim_oif = oif ? oif->info : 0; +	ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; +	ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + +	if (!iif_index || !oif_index) { +		zlog_warn( +			"%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", +			__FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); +		return -2; +	} + +	for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, +			       s_route)) { +		if (s_route->iif == iif_index +		    && s_route->group.s_addr == group.s_addr +		    && s_route->source.s_addr == source.s_addr +		    && s_route->oif_ttls[oif_index]) { +			s_route->oif_ttls[oif_index] = 0; +			s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; +			--s_route->c_oil.oil_ref_count; + +			/* If there are no more outputs then delete the whole +			 * route, otherwise set the route with the new outputs +			 */ +			if (s_route->c_oil.oil_ref_count <= 0 +				    ? pim_mroute_del(&s_route->c_oil, +						     __PRETTY_FUNCTION__) +				    : pim_mroute_add(&s_route->c_oil, +						     __PRETTY_FUNCTION__)) { +				char gifaddr_str[INET_ADDRSTRLEN]; +				char sifaddr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<ifaddr?>", group, gifaddr_str, +					       sizeof(gifaddr_str)); +				pim_inet4_dump("<ifaddr?>", source, sifaddr_str, +					       sizeof(sifaddr_str)); +				zlog_warn( +					"%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", +					__FILE__, __PRETTY_FUNCTION__, +					iif_index, oif_index, gifaddr_str, +					sifaddr_str); + +				s_route->oif_ttls[oif_index] = 1; +				s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; +				++s_route->c_oil.oil_ref_count; + +				return -1; +			} + +			s_route->c_oil.oif_creation[oif_index] = 0; + +			if (s_route->c_oil.oil_ref_count <= 0) { +				listnode_delete(qpim_static_route_list, +						s_route); +				pim_static_route_free(s_route); +			} + +			if (PIM_DEBUG_STATIC) { +				char gifaddr_str[INET_ADDRSTRLEN]; +				char sifaddr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<ifaddr?>", group, gifaddr_str, +					       sizeof(gifaddr_str)); +				pim_inet4_dump("<ifaddr?>", source, sifaddr_str, +					       sizeof(sifaddr_str)); +				zlog_debug( +					"%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", +					__PRETTY_FUNCTION__, iif_index, +					oif_index, gifaddr_str, sifaddr_str); +			} + +			break; +		} +	} + +	if (!node) { +		char gifaddr_str[INET_ADDRSTRLEN]; +		char sifaddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<ifaddr?>", group, gifaddr_str, +			       sizeof(gifaddr_str)); +		pim_inet4_dump("<ifaddr?>", source, sifaddr_str, +			       sizeof(sifaddr_str)); +		zlog_warn( +			"%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", +			__FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, +			gifaddr_str, sifaddr_str); +		return -3; +	} + +	return 0;  } -int -pim_static_write_mroute (struct vty *vty, struct interface *ifp) +int pim_static_write_mroute(struct vty *vty, struct interface *ifp)  { -  struct pim_interface *pim_ifp = ifp->info; -  struct listnode *node; -  struct static_route *sroute; -  int count = 0; -  char sbuf[INET_ADDRSTRLEN]; -  char gbuf[INET_ADDRSTRLEN]; - -  if (!pim_ifp) -    return 0; - -  for (ALL_LIST_ELEMENTS_RO (qpim_static_route_list, node, sroute)) -    { -      pim_inet4_dump ("<ifaddr?>", sroute->group, gbuf, sizeof (gbuf)); -      pim_inet4_dump ("<ifaddr?>", sroute->source, sbuf, sizeof (sbuf)); -      if (sroute->iif == pim_ifp->mroute_vif_index) -        { -          int i; -          for (i = 0; i < MAXVIFS; i++) -            if (sroute->oif_ttls[i]) -              { -                struct interface *oifp = pim_if_find_by_vif_index (i); -                if (sroute->source.s_addr == 0) -                  vty_out (vty, " ip mroute %s %s\n", oifp->name, gbuf); -                else -                  vty_out (vty, " ip mroute %s %s %s\n", oifp->name, gbuf, -                             sbuf); -                count ++; -              } -        } -    } - -  return count; +	struct pim_interface *pim_ifp = ifp->info; +	struct listnode *node; +	struct static_route *sroute; +	int count = 0; +	char sbuf[INET_ADDRSTRLEN]; +	char gbuf[INET_ADDRSTRLEN]; + +	if (!pim_ifp) +		return 0; + +	for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, sroute)) { +		pim_inet4_dump("<ifaddr?>", sroute->group, gbuf, sizeof(gbuf)); +		pim_inet4_dump("<ifaddr?>", sroute->source, sbuf, sizeof(sbuf)); +		if (sroute->iif == pim_ifp->mroute_vif_index) { +			int i; +			for (i = 0; i < MAXVIFS; i++) +				if (sroute->oif_ttls[i]) { +					struct interface *oifp = +						pim_if_find_by_vif_index(i); +					if (sroute->source.s_addr == 0) +						vty_out(vty, +							" ip mroute %s %s\n", +							oifp->name, gbuf); +					else +						vty_out(vty, +							" ip mroute %s %s %s\n", +							oifp->name, gbuf, sbuf); +					count++; +				} +		} +	} + +	return count;  } diff --git a/pimd/pim_static.h b/pimd/pim_static.h index 4b5ef7921d..1114f4b67b 100644 --- a/pimd/pim_static.h +++ b/pimd/pim_static.h @@ -25,19 +25,21 @@  #include "if.h"  struct static_route { -   /* Each static route is unique by these pair of addresses */ -   struct in_addr group; -   struct in_addr source; +	/* Each static route is unique by these pair of addresses */ +	struct in_addr group; +	struct in_addr source; -   struct channel_oil c_oil; -   ifindex_t          iif; -   unsigned char  oif_ttls[MAXVIFS]; +	struct channel_oil c_oil; +	ifindex_t iif; +	unsigned char oif_ttls[MAXVIFS];  };  void pim_static_route_free(struct static_route *s_route); -int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source); -int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source); -int pim_static_write_mroute (struct vty *vty, struct interface *ifp); +int pim_static_add(struct interface *iif, struct interface *oif, +		   struct in_addr group, struct in_addr source); +int pim_static_del(struct interface *iif, struct interface *oif, +		   struct in_addr group, struct in_addr source); +int pim_static_write_mroute(struct vty *vty, struct interface *ifp);  #endif /* PIM_STATIC_H_ */ diff --git a/pimd/pim_str.c b/pimd/pim_str.c index d1219a8681..fa1a6e624c 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -27,62 +27,62 @@  #include "pim_str.h" -void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size) +void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, +		   int buf_size)  { -  int save_errno = errno; +	int save_errno = errno; -  if (!inet_ntop(p->family, &p->u.prefix, buf, buf_size)) { -    zlog_warn("pim_addr_dump: inet_ntop(buf_size=%d): errno=%d: %s", -	      buf_size, errno, safe_strerror(errno)); -    if (onfail) -      snprintf(buf, buf_size, "%s", onfail); -  } +	if (!inet_ntop(p->family, &p->u.prefix, buf, buf_size)) { +		zlog_warn("pim_addr_dump: inet_ntop(buf_size=%d): errno=%d: %s", +			  buf_size, errno, safe_strerror(errno)); +		if (onfail) +			snprintf(buf, buf_size, "%s", onfail); +	} -  errno = save_errno; +	errno = save_errno;  } -void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size) +void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, +		    int buf_size)  { -  int save_errno = errno; - -  if (addr.s_addr == INADDR_ANY) -    strcpy(buf, "*"); -  else -    { -      if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { -        zlog_warn("pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", -	          buf_size, errno, safe_strerror(errno)); -      if (onfail) -        snprintf(buf, buf_size, "%s", onfail); -    } -  } - -  errno = save_errno; +	int save_errno = errno; + +	if (addr.s_addr == INADDR_ANY) +		strcpy(buf, "*"); +	else { +		if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { +			zlog_warn( +				"pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", +				buf_size, errno, safe_strerror(errno)); +			if (onfail) +				snprintf(buf, buf_size, "%s", onfail); +		} +	} + +	errno = save_errno;  } -char * -pim_str_sg_dump (const struct prefix_sg *sg) +char *pim_str_sg_dump(const struct prefix_sg *sg)  { -  char src_str[INET_ADDRSTRLEN]; -  char grp_str[INET_ADDRSTRLEN]; -  static char sg_str[PIM_SG_LEN]; +	char src_str[INET_ADDRSTRLEN]; +	char grp_str[INET_ADDRSTRLEN]; +	static char sg_str[PIM_SG_LEN]; -  pim_inet4_dump ("<src?>", sg->src, src_str, sizeof(src_str)); -  pim_inet4_dump ("<grp?>", sg->grp, grp_str, sizeof(grp_str)); -  snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); +	pim_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str)); +	pim_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str)); +	snprintf(sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); -  return sg_str; +	return sg_str;  } -char * -pim_str_sg_set (const struct prefix_sg *sg, char *sg_str) +char *pim_str_sg_set(const struct prefix_sg *sg, char *sg_str)  { -  char src_str[INET_ADDRSTRLEN]; -  char grp_str[INET_ADDRSTRLEN]; +	char src_str[INET_ADDRSTRLEN]; +	char grp_str[INET_ADDRSTRLEN]; -  pim_inet4_dump ("<src?>", sg->src, src_str, sizeof(src_str)); -  pim_inet4_dump ("<grp?>", sg->grp, grp_str, sizeof(grp_str)); -  snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); +	pim_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str)); +	pim_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str)); +	snprintf(sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); -  return sg_str; +	return sg_str;  } diff --git a/pimd/pim_str.h b/pimd/pim_str.h index 0ca517102a..12a33a810f 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -35,9 +35,11 @@   */  #define PIM_SG_LEN 36 -void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size); -void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); -char *pim_str_sg_dump (const struct prefix_sg *sg); -char *pim_str_sg_set (const struct prefix_sg *sg, char *sg_str); +void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, +		   int buf_size); +void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, +		    int buf_size); +char *pim_str_sg_dump(const struct prefix_sg *sg); +char *pim_str_sg_set(const struct prefix_sg *sg, char *sg_str);  #endif diff --git a/pimd/pim_time.c b/pimd/pim_time.c index 406fec58d3..6f011da43e 100644 --- a/pimd/pim_time.c +++ b/pimd/pim_time.c @@ -30,16 +30,15 @@  static int gettime_monotonic(struct timeval *tv)  { -  int result; +	int result; -  result = gettimeofday(tv, 0); -  if (result) { -    zlog_err("%s: gettimeofday() failure: errno=%d: %s", -	     __PRETTY_FUNCTION__, -	     errno, safe_strerror(errno)); -  } +	result = gettimeofday(tv, 0); +	if (result) { +		zlog_err("%s: gettimeofday() failure: errno=%d: %s", +			 __PRETTY_FUNCTION__, errno, safe_strerror(errno)); +	} -  return result; +	return result;  }  /* @@ -48,16 +47,15 @@ static int gettime_monotonic(struct timeval *tv)  */  int64_t pim_time_monotonic_sec()  { -  struct timeval now_tv; +	struct timeval now_tv; -  if (gettime_monotonic(&now_tv)) { -    zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", -	     __PRETTY_FUNCTION__, -	     errno, safe_strerror(errno)); -    return -1; -  } +	if (gettime_monotonic(&now_tv)) { +		zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", +			 __PRETTY_FUNCTION__, errno, safe_strerror(errno)); +		return -1; +	} -  return now_tv.tv_sec; +	return now_tv.tv_sec;  }  /* @@ -66,117 +64,111 @@ int64_t pim_time_monotonic_sec()  */  int64_t pim_time_monotonic_dsec()  { -  struct timeval now_tv; -  int64_t        now_dsec; +	struct timeval now_tv; +	int64_t now_dsec; -  if (gettime_monotonic(&now_tv)) { -    zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", -	     __PRETTY_FUNCTION__, -	     errno, safe_strerror(errno)); -    return -1; -  } +	if (gettime_monotonic(&now_tv)) { +		zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", +			 __PRETTY_FUNCTION__, errno, safe_strerror(errno)); +		return -1; +	} -  now_dsec = ((int64_t) now_tv.tv_sec) * 10 + ((int64_t) now_tv.tv_usec) / 100000; +	now_dsec = ((int64_t)now_tv.tv_sec) * 10 +		   + ((int64_t)now_tv.tv_usec) / 100000; -  return now_dsec; +	return now_dsec;  } -int64_t -pim_time_monotonic_usec (void) +int64_t pim_time_monotonic_usec(void)  { -  struct timeval now_tv; -  int64_t        now_dsec; +	struct timeval now_tv; +	int64_t now_dsec; -  if (gettime_monotonic(&now_tv)) { -    zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", -             __PRETTY_FUNCTION__, -             errno, safe_strerror(errno)); -    return -1; -  } +	if (gettime_monotonic(&now_tv)) { +		zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", +			 __PRETTY_FUNCTION__, errno, safe_strerror(errno)); +		return -1; +	} -  now_dsec = ((int64_t) now_tv.tv_sec) * 1000000 + ((int64_t) now_tv.tv_usec); - -  return now_dsec; +	now_dsec = +		((int64_t)now_tv.tv_sec) * 1000000 + ((int64_t)now_tv.tv_usec); +	return now_dsec;  }  int pim_time_mmss(char *buf, int buf_size, long sec)  { -  long mm; -  int wr; +	long mm; +	int wr; + +	zassert(buf_size >= 5); -  zassert(buf_size >= 5); +	mm = sec / 60; +	sec %= 60; -  mm = sec / 60; -  sec %= 60; -   -  wr = snprintf(buf, buf_size, "%02ld:%02ld", mm, sec); +	wr = snprintf(buf, buf_size, "%02ld:%02ld", mm, sec); -  return wr != 8; +	return wr != 8;  }  static int pim_time_hhmmss(char *buf, int buf_size, long sec)  { -  long hh; -  long mm; -  int wr; +	long hh; +	long mm; +	int wr; + +	zassert(buf_size >= 8); -  zassert(buf_size >= 8); +	hh = sec / 3600; +	sec %= 3600; +	mm = sec / 60; +	sec %= 60; -  hh = sec / 3600; -  sec %= 3600; -  mm = sec / 60; -  sec %= 60; -   -  wr = snprintf(buf, buf_size, "%02ld:%02ld:%02ld", hh, mm, sec); +	wr = snprintf(buf, buf_size, "%02ld:%02ld:%02ld", hh, mm, sec); -  return wr != 8; +	return wr != 8;  }  void pim_time_timer_to_mmss(char *buf, int buf_size, struct thread *t_timer)  { -  if (t_timer) { -    pim_time_mmss(buf, buf_size, -		  thread_timer_remain_second(t_timer)); -  } -  else { -    snprintf(buf, buf_size, "--:--"); -  } +	if (t_timer) { +		pim_time_mmss(buf, buf_size, +			      thread_timer_remain_second(t_timer)); +	} else { +		snprintf(buf, buf_size, "--:--"); +	}  }  void pim_time_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer)  { -  if (t_timer) { -    pim_time_hhmmss(buf, buf_size, -		    thread_timer_remain_second(t_timer)); -  } -  else { -    snprintf(buf, buf_size, "--:--:--"); -  } +	if (t_timer) { +		pim_time_hhmmss(buf, buf_size, +				thread_timer_remain_second(t_timer)); +	} else { +		snprintf(buf, buf_size, "--:--:--"); +	}  }  void pim_time_uptime(char *buf, int buf_size, int64_t uptime_sec)  { -  zassert(buf_size >= 8); +	zassert(buf_size >= 8); -  pim_time_hhmmss(buf, buf_size, uptime_sec); +	pim_time_hhmmss(buf, buf_size, uptime_sec);  }  void pim_time_uptime_begin(char *buf, int buf_size, int64_t now, int64_t begin)  { -  if (begin > 0) -    pim_time_uptime(buf, buf_size, now - begin); -  else -    snprintf(buf, buf_size, "--:--:--"); +	if (begin > 0) +		pim_time_uptime(buf, buf_size, now - begin); +	else +		snprintf(buf, buf_size, "--:--:--");  }  long pim_time_timer_remain_msec(struct thread *t_timer)  { -  /* FIXME: Actually fetch msec resolution from thread */ +	/* FIXME: Actually fetch msec resolution from thread */ -  /* no timer thread running means timer has expired: return 0 */ +	/* no timer thread running means timer has expired: return 0 */ -  return t_timer ? -    1000 * thread_timer_remain_second(t_timer) : -    0; +	return t_timer ? 1000 * thread_timer_remain_second(t_timer) : 0;  } diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 550fdde8eb..6d7adf2422 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -29,67 +29,61 @@  #include "pim_str.h"  #include "pim_msg.h" -uint8_t *pim_tlv_append_uint16(uint8_t *buf, -			       const uint8_t *buf_pastend, -			       uint16_t option_type, -			       uint16_t option_value) +uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend, +			       uint16_t option_type, uint16_t option_value)  { -  uint16_t option_len = 2; +	uint16_t option_len = 2; -  if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) -    return NULL; +	if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) +		return NULL; -  *(uint16_t *) buf = htons(option_type); -  buf += 2; -  *(uint16_t *) buf = htons(option_len); -  buf += 2; -  *(uint16_t *) buf = htons(option_value); -  buf += option_len; +	*(uint16_t *)buf = htons(option_type); +	buf += 2; +	*(uint16_t *)buf = htons(option_len); +	buf += 2; +	*(uint16_t *)buf = htons(option_value); +	buf += option_len; -  return buf; +	return buf;  } -uint8_t *pim_tlv_append_2uint16(uint8_t *buf, -				const uint8_t *buf_pastend, -				uint16_t option_type, -				uint16_t option_value1, +uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend, +				uint16_t option_type, uint16_t option_value1,  				uint16_t option_value2)  { -  uint16_t option_len = 4; +	uint16_t option_len = 4; -  if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) -    return NULL; +	if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) +		return NULL; -  *(uint16_t *) buf = htons(option_type); -  buf += 2; -  *(uint16_t *) buf = htons(option_len); -  buf += 2; -  *(uint16_t *) buf = htons(option_value1); -  buf += 2; -  *(uint16_t *) buf = htons(option_value2); -  buf += 2; +	*(uint16_t *)buf = htons(option_type); +	buf += 2; +	*(uint16_t *)buf = htons(option_len); +	buf += 2; +	*(uint16_t *)buf = htons(option_value1); +	buf += 2; +	*(uint16_t *)buf = htons(option_value2); +	buf += 2; -  return buf; +	return buf;  } -uint8_t *pim_tlv_append_uint32(uint8_t *buf, -			       const uint8_t *buf_pastend, -			       uint16_t option_type, -			       uint32_t option_value) +uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend, +			       uint16_t option_type, uint32_t option_value)  { -  uint16_t option_len = 4; +	uint16_t option_len = 4; -  if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) -    return NULL; +	if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) +		return NULL; -  *(uint16_t *) buf = htons(option_type); -  buf += 2; -  *(uint16_t *) buf = htons(option_len); -  buf += 2; -  pim_write_uint32(buf, option_value); -  buf += option_len; +	*(uint16_t *)buf = htons(option_type); +	buf += 2; +	*(uint16_t *)buf = htons(option_len); +	buf += 2; +	pim_write_uint32(buf, option_value); +	buf += option_len; -  return buf; +	return buf;  }  #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) @@ -108,7 +102,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf,   *       The PIM address family of the 'Unicast Address' field of this   *       address.   * - *       Values 0-127 are as assigned by the IANA for Internet Address   *       Families in [7].  Values 128-250 are reserved to be assigned by + *       Values 0-127 are as assigned by the IANA for Internet Address   * + * Families in [7].  Values 128-250 are reserved to be assigned by   *       the IANA for PIM-specific Address Families.  Values 251 though   *       255 are designated for private use.  As there is no assignment   *       authority for this space, collisions should be expected. @@ -122,31 +117,33 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf,   *       The unicast address as represented by the given Address Family   *       and Encoding Type.   */ -int -pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) +int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p)  { -  switch (p->family) -    { -    case AF_INET: -      *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ -      ++buf; -      *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */ -      ++buf; -      memcpy (buf, &p->u.prefix4, sizeof (struct in_addr)); -      return ucast_ipv4_encoding_len; -      break; -    case AF_INET6: -      *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; -      ++buf; -      *(uint8_t *)buf = 0; -      ++buf; -      memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr)); -      return ucast_ipv6_encoding_len; -      break; -    default: -      return 0; -      break; -    } +	switch (p->family) { +	case AF_INET: +		*(uint8_t *)buf = +			PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != +							PIM_MSG_ADDRESS_FAMILY_IPV4 +							*/ +		++buf; +		*(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC +					4601: 4.9.1) */ +		++buf; +		memcpy(buf, &p->u.prefix4, sizeof(struct in_addr)); +		return ucast_ipv4_encoding_len; +		break; +	case AF_INET6: +		*(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; +		++buf; +		*(uint8_t *)buf = 0; +		++buf; +		memcpy(buf, &p->u.prefix6, sizeof(struct in6_addr)); +		return ucast_ipv6_encoding_len; +		break; +	default: +		return 0; +		break; +	}  }  #define group_ipv4_encoding_len (4 + sizeof (struct in_addr)) @@ -194,614 +191,604 @@ pim_encode_addr_ucast (uint8_t *buf, struct prefix *p)   *  Group multicast Address   *       Contains the group address.   */ -int -pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group) +int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope, +			  struct in_addr group)  { -  uint8_t flags = 0; - -  flags |= bidir << 8; -  flags |= scope; - -  switch (afi) -    { -    case AFI_IP: -      *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; -      ++buf; -      *(uint8_t *)buf = 0; -      ++buf; -      *(uint8_t *)buf = flags; -      ++buf; -      *(uint8_t *)buf = 32; -      ++buf; -      memcpy (buf, &group, sizeof (struct in_addr)); -      return group_ipv4_encoding_len; -      break; -    default: -      return 0; -      break; -    } +	uint8_t flags = 0; + +	flags |= bidir << 8; +	flags |= scope; + +	switch (afi) { +	case AFI_IP: +		*(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; +		++buf; +		*(uint8_t *)buf = 0; +		++buf; +		*(uint8_t *)buf = flags; +		++buf; +		*(uint8_t *)buf = 32; +		++buf; +		memcpy(buf, &group, sizeof(struct in_addr)); +		return group_ipv4_encoding_len; +		break; +	default: +		return 0; +		break; +	}  } -uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, -				       const uint8_t *buf_pastend, -				       struct list *ifconnected, -                                       int family) +uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, +				       struct list *ifconnected, int family)  { -  struct listnode *node; -  uint16_t option_len = 0; -  uint8_t *curr; -  size_t uel; - -  node = listhead(ifconnected); - -  /* Empty address list ? */ -  if (!node) { -    return buf; -  } - -  if (family == AF_INET) -    uel = ucast_ipv4_encoding_len; -  else -    uel = ucast_ipv6_encoding_len; - -  /* Scan secondary address list */ -  curr = buf + 4; /* skip T and L */ -  for (; node; node = listnextnode(node)) { -    struct connected *ifc = listgetdata(node); -    struct prefix *p = ifc->address; -    int l_encode; - -    if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) -      continue; - -    if ((curr + uel) > buf_pastend) -          return 0; - -    if (p->family != family) -      continue; - -    l_encode = pim_encode_addr_ucast (curr, p); -    curr += l_encode; -    option_len += l_encode; -  } - -  if (PIM_DEBUG_PIM_TRACE_DETAIL) { -    zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu", -	       __PRETTY_FUNCTION__, -	       option_len / uel); -  } - -  if (option_len < 1) { -    /* Empty secondary unicast IPv4 address list */ -    return buf; -  } - -  /* -   * Write T and L -   */ -  *(uint16_t *) buf       = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST); -  *(uint16_t *) (buf + 2) = htons(option_len); - -  return curr; +	struct listnode *node; +	uint16_t option_len = 0; +	uint8_t *curr; +	size_t uel; + +	node = listhead(ifconnected); + +	/* Empty address list ? */ +	if (!node) { +		return buf; +	} + +	if (family == AF_INET) +		uel = ucast_ipv4_encoding_len; +	else +		uel = ucast_ipv6_encoding_len; + +	/* Scan secondary address list */ +	curr = buf + 4; /* skip T and L */ +	for (; node; node = listnextnode(node)) { +		struct connected *ifc = listgetdata(node); +		struct prefix *p = ifc->address; +		int l_encode; + +		if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) +			continue; + +		if ((curr + uel) > buf_pastend) +			return 0; + +		if (p->family != family) +			continue; + +		l_encode = pim_encode_addr_ucast(curr, p); +		curr += l_encode; +		option_len += l_encode; +	} + +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		zlog_debug( +			"%s: number of encoded secondary unicast IPv4 addresses: %zu", +			__PRETTY_FUNCTION__, option_len / uel); +	} + +	if (option_len < 1) { +		/* Empty secondary unicast IPv4 address list */ +		return buf; +	} + +	/* +	 * Write T and L +	 */ +	*(uint16_t *)buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST); +	*(uint16_t *)(buf + 2) = htons(option_len); + +	return curr;  }  static int check_tlv_length(const char *label, const char *tlv_name,  			    const char *ifname, struct in_addr src_addr,  			    int correct_len, int option_len)  { -  if (option_len != correct_len) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", -	      label, tlv_name, -	      option_len, correct_len, -	      src_str, ifname); -    return -1; -  } - -  return 0; +	if (option_len != correct_len) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn( +			"%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", +			label, tlv_name, option_len, correct_len, src_str, +			ifname); +		return -1; +	} + +	return 0;  } -static void check_tlv_redefinition_uint16(const char *label, const char *tlv_name, -					  const char *ifname, struct in_addr src_addr, -					  pim_hello_options options, -					  pim_hello_options opt_mask, -					  uint16_t new, uint16_t old) +static void check_tlv_redefinition_uint16( +	const char *label, const char *tlv_name, const char *ifname, +	struct in_addr src_addr, pim_hello_options options, +	pim_hello_options opt_mask, uint16_t new, uint16_t old)  { -  if (PIM_OPTION_IS_SET(options, opt_mask)) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", -	      label, tlv_name, -	      new, old, -	      src_str, ifname); -  } +	if (PIM_OPTION_IS_SET(options, opt_mask)) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn( +			"%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", +			label, tlv_name, new, old, src_str, ifname); +	}  } -static void check_tlv_redefinition_uint32(const char *label, const char *tlv_name, -					  const char *ifname, struct in_addr src_addr, -					  pim_hello_options options, -					  pim_hello_options opt_mask, -					  uint32_t new, uint32_t old) +static void check_tlv_redefinition_uint32( +	const char *label, const char *tlv_name, const char *ifname, +	struct in_addr src_addr, pim_hello_options options, +	pim_hello_options opt_mask, uint32_t new, uint32_t old)  { -  if (PIM_OPTION_IS_SET(options, opt_mask)) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", -	      label, tlv_name, -	      new, old, -	      src_str, ifname); -  } +	if (PIM_OPTION_IS_SET(options, opt_mask)) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn( +			"%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", +			label, tlv_name, new, old, src_str, ifname); +	}  } -static void check_tlv_redefinition_uint32_hex(const char *label, const char *tlv_name, -					      const char *ifname, struct in_addr src_addr, -					      pim_hello_options options, -					      pim_hello_options opt_mask, -					      uint32_t new, uint32_t old) +static void check_tlv_redefinition_uint32_hex( +	const char *label, const char *tlv_name, const char *ifname, +	struct in_addr src_addr, pim_hello_options options, +	pim_hello_options opt_mask, uint32_t new, uint32_t old)  { -  if (PIM_OPTION_IS_SET(options, opt_mask)) { -    char src_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -    zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", -	      label, tlv_name, -	      new, old, -	      src_str, ifname); -  } +	if (PIM_OPTION_IS_SET(options, opt_mask)) { +		char src_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); +		zlog_warn( +			"%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", +			label, tlv_name, new, old, src_str, ifname); +	}  }  int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,  			   pim_hello_options *hello_options, -			   uint16_t *hello_option_holdtime, -			   uint16_t option_len, -			   const uint8_t *tlv_curr)  +			   uint16_t *hello_option_holdtime, uint16_t option_len, +			   const uint8_t *tlv_curr)  { -  const char *label = "holdtime"; - -  if (check_tlv_length(__PRETTY_FUNCTION__, label, -		       ifname, src_addr, -		       sizeof(uint16_t), option_len)) { -    return -1; -  } -   -  check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, label, -				ifname, src_addr, -				*hello_options, PIM_OPTION_MASK_HOLDTIME, -				PIM_TLV_GET_HOLDTIME(tlv_curr), -				*hello_option_holdtime); -   -  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME); -   -  *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr); -   -  return 0; +	const char *label = "holdtime"; + +	if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, +			     sizeof(uint16_t), option_len)) { +		return -1; +	} + +	check_tlv_redefinition_uint16( +		__PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options, +		PIM_OPTION_MASK_HOLDTIME, PIM_TLV_GET_HOLDTIME(tlv_curr), +		*hello_option_holdtime); + +	PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME); + +	*hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr); + +	return 0;  }  int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,  				  pim_hello_options *hello_options,  				  uint16_t *hello_option_propagation_delay,  				  uint16_t *hello_option_override_interval, -				  uint16_t option_len, -				  const uint8_t *tlv_curr)  +				  uint16_t option_len, const uint8_t *tlv_curr)  { -  if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay", -		       ifname, src_addr, -		       sizeof(uint32_t), option_len)) { -    return -1; -  } -   -  check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay", -				ifname, src_addr, -				*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY, -				PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr), -				*hello_option_propagation_delay); -   -  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY); -   -  *hello_option_propagation_delay = PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr); -  if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) { -    PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); -  } -  else { -    PIM_OPTION_UNSET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); -  } -  ++tlv_curr; -  ++tlv_curr; -  *hello_option_override_interval = PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr); -   -  return 0; +	if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay", ifname, +			     src_addr, sizeof(uint32_t), option_len)) { +		return -1; +	} + +	check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay", +				      ifname, src_addr, *hello_options, +				      PIM_OPTION_MASK_LAN_PRUNE_DELAY, +				      PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr), +				      *hello_option_propagation_delay); + +	PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY); + +	*hello_option_propagation_delay = +		PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr); +	if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) { +		PIM_OPTION_SET(*hello_options, +			       PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); +	} else { +		PIM_OPTION_UNSET(*hello_options, +				 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); +	} +	++tlv_curr; +	++tlv_curr; +	*hello_option_override_interval = +		PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr); + +	return 0;  }  int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,  			      pim_hello_options *hello_options,  			      uint32_t *hello_option_dr_priority, -			      uint16_t option_len, -			      const uint8_t *tlv_curr)  +			      uint16_t option_len, const uint8_t *tlv_curr)  { -  const char *label = "dr_priority"; - -  if (check_tlv_length(__PRETTY_FUNCTION__, label, -		       ifname, src_addr, -		       sizeof(uint32_t), option_len)) { -    return -1; -  } -   -  check_tlv_redefinition_uint32(__PRETTY_FUNCTION__, label, -				ifname, src_addr, -				*hello_options, PIM_OPTION_MASK_DR_PRIORITY, -				PIM_TLV_GET_DR_PRIORITY(tlv_curr), -				*hello_option_dr_priority); -   -  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY); -   -  *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr); - -  return 0; +	const char *label = "dr_priority"; + +	if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, +			     sizeof(uint32_t), option_len)) { +		return -1; +	} + +	check_tlv_redefinition_uint32( +		__PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options, +		PIM_OPTION_MASK_DR_PRIORITY, PIM_TLV_GET_DR_PRIORITY(tlv_curr), +		*hello_option_dr_priority); + +	PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY); + +	*hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr); + +	return 0;  }  int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,  				pim_hello_options *hello_options,  				uint32_t *hello_option_generation_id, -				uint16_t option_len, -				const uint8_t *tlv_curr)  +				uint16_t option_len, const uint8_t *tlv_curr)  { -  const char *label = "generation_id"; - -  if (check_tlv_length(__PRETTY_FUNCTION__, label, -		       ifname, src_addr, -		       sizeof(uint32_t), option_len)) { -    return -1; -  } -   -  check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label, -				    ifname, src_addr, -				    *hello_options, PIM_OPTION_MASK_GENERATION_ID, -				    PIM_TLV_GET_GENERATION_ID(tlv_curr), -				    *hello_option_generation_id); -   -  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID); -   -  *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr); -   -  return 0; +	const char *label = "generation_id"; + +	if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, +			     sizeof(uint32_t), option_len)) { +		return -1; +	} + +	check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label, ifname, +					  src_addr, *hello_options, +					  PIM_OPTION_MASK_GENERATION_ID, +					  PIM_TLV_GET_GENERATION_ID(tlv_curr), +					  *hello_option_generation_id); + +	PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID); + +	*hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr); + +	return 0;  } -int -pim_parse_addr_ucast (struct prefix *p, -		      const uint8_t *buf, -		      int buf_size) +int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size)  { -  const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ -  const uint8_t *addr; -  const uint8_t *pastend; -  int family; -  int type; - -  if (buf_size < ucast_encoding_min_len) { -    zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d", -	      __PRETTY_FUNCTION__, -	      buf_size, ucast_encoding_min_len); -    return -1; -  } - -  addr = buf; -  pastend = buf + buf_size; - -  family = *addr++; -  type = *addr++; - -  if (type) { -    zlog_warn("%s: unknown unicast address encoding type=%d", -	      __PRETTY_FUNCTION__, -	      type); -    return -2; -  } - -  switch (family) { -  case PIM_MSG_ADDRESS_FAMILY_IPV4: -    if ((addr + sizeof(struct in_addr)) > pastend) { -      zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu", -		__PRETTY_FUNCTION__, -		pastend - addr, sizeof(struct in_addr)); -      return -3; -    } - -    p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ -    memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); -    p->prefixlen = IPV4_MAX_PREFIXLEN; -    addr += sizeof(struct in_addr); - -    break; -  case PIM_MSG_ADDRESS_FAMILY_IPV6: -    if ((addr + sizeof(struct in6_addr)) > pastend) { -      zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu", -                 __PRETTY_FUNCTION__, -                 pastend - addr, sizeof(struct in6_addr)); -      return -3; -    } - -    p->family = AF_INET6; -    p->prefixlen = IPV6_MAX_PREFIXLEN; -    memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); -    addr += sizeof(struct in6_addr); - -    break; -  default: -    { -      zlog_warn("%s: unknown unicast address encoding family=%d from", -		__PRETTY_FUNCTION__, -		family); -      return -4; -    } -  } - -  return addr - buf; +	const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ +	const uint8_t *addr; +	const uint8_t *pastend; +	int family; +	int type; + +	if (buf_size < ucast_encoding_min_len) { +		zlog_warn( +			"%s: unicast address encoding overflow: left=%d needed=%d", +			__PRETTY_FUNCTION__, buf_size, ucast_encoding_min_len); +		return -1; +	} + +	addr = buf; +	pastend = buf + buf_size; + +	family = *addr++; +	type = *addr++; + +	if (type) { +		zlog_warn("%s: unknown unicast address encoding type=%d", +			  __PRETTY_FUNCTION__, type); +		return -2; +	} + +	switch (family) { +	case PIM_MSG_ADDRESS_FAMILY_IPV4: +		if ((addr + sizeof(struct in_addr)) > pastend) { +			zlog_warn( +				"%s: IPv4 unicast address overflow: left=%zd needed=%zu", +				__PRETTY_FUNCTION__, pastend - addr, +				sizeof(struct in_addr)); +			return -3; +		} + +		p->family = AF_INET; /* notice: AF_INET != +					PIM_MSG_ADDRESS_FAMILY_IPV4 */ +		memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); +		p->prefixlen = IPV4_MAX_PREFIXLEN; +		addr += sizeof(struct in_addr); + +		break; +	case PIM_MSG_ADDRESS_FAMILY_IPV6: +		if ((addr + sizeof(struct in6_addr)) > pastend) { +			zlog_warn( +				"%s: IPv6 unicast address overflow: left=%zd needed %zu", +				__PRETTY_FUNCTION__, pastend - addr, +				sizeof(struct in6_addr)); +			return -3; +		} + +		p->family = AF_INET6; +		p->prefixlen = IPV6_MAX_PREFIXLEN; +		memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); +		addr += sizeof(struct in6_addr); + +		break; +	default: { +		zlog_warn("%s: unknown unicast address encoding family=%d from", +			  __PRETTY_FUNCTION__, family); +		return -4; +	} +	} + +	return addr - buf;  } -int -pim_parse_addr_group (struct prefix_sg *sg, -		      const uint8_t *buf, -		      int buf_size) +int pim_parse_addr_group(struct prefix_sg *sg, const uint8_t *buf, int buf_size)  { -  const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ -  const uint8_t *addr; -  const uint8_t *pastend; -  int family; -  int type; -  int mask_len; - -  if (buf_size < grp_encoding_min_len) { -    zlog_warn("%s: group address encoding overflow: left=%d needed=%d", -	      __PRETTY_FUNCTION__, -	      buf_size, grp_encoding_min_len); -    return -1; -  } - -  addr = buf; -  pastend = buf + buf_size; - -  family = *addr++; -  type = *addr++; -  //++addr; -  ++addr; /* skip b_reserved_z fields */ -  mask_len = *addr++; - -  switch (family) { -  case PIM_MSG_ADDRESS_FAMILY_IPV4: -    if (type) { -      zlog_warn("%s: unknown group address encoding type=%d from", -		__PRETTY_FUNCTION__, type); -      return -2; -    } - -    if ((addr + sizeof(struct in_addr)) > pastend) { -      zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from", -		__PRETTY_FUNCTION__, -		pastend - addr, sizeof(struct in_addr)); -      return -3; -    } - -    memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); - -    addr += sizeof(struct in_addr); - -    break; -  default: -    { -      zlog_warn("%s: unknown group address encoding family=%d mask_len=%d from", -		__PRETTY_FUNCTION__, family, mask_len); -      return -4; -    } -  } - -  return addr - buf; +	const int grp_encoding_min_len = +		4; /* 1 family + 1 type + 1 reserved + 1 addr */ +	const uint8_t *addr; +	const uint8_t *pastend; +	int family; +	int type; +	int mask_len; + +	if (buf_size < grp_encoding_min_len) { +		zlog_warn( +			"%s: group address encoding overflow: left=%d needed=%d", +			__PRETTY_FUNCTION__, buf_size, grp_encoding_min_len); +		return -1; +	} + +	addr = buf; +	pastend = buf + buf_size; + +	family = *addr++; +	type = *addr++; +	//++addr; +	++addr; /* skip b_reserved_z fields */ +	mask_len = *addr++; + +	switch (family) { +	case PIM_MSG_ADDRESS_FAMILY_IPV4: +		if (type) { +			zlog_warn( +				"%s: unknown group address encoding type=%d from", +				__PRETTY_FUNCTION__, type); +			return -2; +		} + +		if ((addr + sizeof(struct in_addr)) > pastend) { +			zlog_warn( +				"%s: IPv4 group address overflow: left=%zd needed=%zu from", +				__PRETTY_FUNCTION__, pastend - addr, +				sizeof(struct in_addr)); +			return -3; +		} + +		memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); + +		addr += sizeof(struct in_addr); + +		break; +	default: { +		zlog_warn( +			"%s: unknown group address encoding family=%d mask_len=%d from", +			__PRETTY_FUNCTION__, family, mask_len); +		return -4; +	} +	} + +	return addr - buf;  } -int -pim_parse_addr_source(struct prefix_sg *sg, -		      uint8_t *flags, -		      const uint8_t *buf, -		      int buf_size) +int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, +			  const uint8_t *buf, int buf_size)  { -  const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ -  const uint8_t *addr; -  const uint8_t *pastend; -  int family; -  int type; -  int mask_len; - -  if (buf_size < src_encoding_min_len) { -    zlog_warn("%s: source address encoding overflow: left=%d needed=%d", -	      __PRETTY_FUNCTION__, -	      buf_size, src_encoding_min_len); -    return -1; -  } - -  addr = buf; -  pastend = buf + buf_size; - -  family = *addr++; -  type = *addr++; -  *flags = *addr++; -  mask_len = *addr++; - -  if (type) { -    zlog_warn("%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x", -	      __PRETTY_FUNCTION__, -	      type, -	      buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); -    return -2; -  } - -  switch (family) { -  case PIM_MSG_ADDRESS_FAMILY_IPV4: -    if ((addr + sizeof(struct in_addr)) > pastend) { -      zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu", -		__PRETTY_FUNCTION__, -		pastend - addr, sizeof(struct in_addr)); -      return -3; -    } - -    memcpy(&sg->src, addr, sizeof(struct in_addr)); - -    /*  -       RFC 4601: 4.9.1  Encoded Source and Group Address Formats - -       Encoded-Source Address - -       The mask length MUST be equal to the mask length in bits for -       the given Address Family and Encoding Type (32 for IPv4 native -       and 128 for IPv6 native).  A router SHOULD ignore any messages -       received with any other mask length. -    */ -    if (mask_len != 32) { -      zlog_warn("%s: IPv4 bad source address mask: %d", -		__PRETTY_FUNCTION__, mask_len); -      return -4; -    } - -    addr += sizeof(struct in_addr); - -    break; -  default: -    { -      zlog_warn("%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x", -		__PRETTY_FUNCTION__, -		family, -		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); -      return -5; -    } -  } - -  return addr - buf; -} +	const int src_encoding_min_len = +		4; /* 1 family + 1 type + 1 reserved + 1 addr */ +	const uint8_t *addr; +	const uint8_t *pastend; +	int family; +	int type; +	int mask_len; + +	if (buf_size < src_encoding_min_len) { +		zlog_warn( +			"%s: source address encoding overflow: left=%d needed=%d", +			__PRETTY_FUNCTION__, buf_size, src_encoding_min_len); +		return -1; +	} + +	addr = buf; +	pastend = buf + buf_size; + +	family = *addr++; +	type = *addr++; +	*flags = *addr++; +	mask_len = *addr++; -#define FREE_ADDR_LIST(hello_option_addr_list) \ -{ \ -  if (hello_option_addr_list) { \ -    list_delete(hello_option_addr_list); \ -    hello_option_addr_list = 0; \ -  } \ +	if (type) { +		zlog_warn( +			"%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x", +			__PRETTY_FUNCTION__, type, buf[0], buf[1], buf[2], +			buf[3], buf[4], buf[5], buf[6], buf[7]); +		return -2; +	} + +	switch (family) { +	case PIM_MSG_ADDRESS_FAMILY_IPV4: +		if ((addr + sizeof(struct in_addr)) > pastend) { +			zlog_warn( +				"%s: IPv4 source address overflow: left=%zd needed=%zu", +				__PRETTY_FUNCTION__, pastend - addr, +				sizeof(struct in_addr)); +			return -3; +		} + +		memcpy(&sg->src, addr, sizeof(struct in_addr)); + +		/* +		   RFC 4601: 4.9.1  Encoded Source and Group Address Formats + +		   Encoded-Source Address + +		   The mask length MUST be equal to the mask length in bits for +		   the given Address Family and Encoding Type (32 for IPv4 +		   native +		   and 128 for IPv6 native).  A router SHOULD ignore any +		   messages +		   received with any other mask length. +		*/ +		if (mask_len != 32) { +			zlog_warn("%s: IPv4 bad source address mask: %d", +				  __PRETTY_FUNCTION__, mask_len); +			return -4; +		} + +		addr += sizeof(struct in_addr); + +		break; +	default: { +		zlog_warn( +			"%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x", +			__PRETTY_FUNCTION__, family, buf[0], buf[1], buf[2], +			buf[3], buf[4], buf[5], buf[6], buf[7]); +		return -5; +	} +	} + +	return addr - buf;  } +#define FREE_ADDR_LIST(hello_option_addr_list)                                 \ +	{                                                                      \ +		if (hello_option_addr_list) {                                  \ +			list_delete(hello_option_addr_list);                   \ +			hello_option_addr_list = 0;                            \ +		}                                                              \ +	} +  int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,  			    pim_hello_options *hello_options,  			    struct list **hello_option_addr_list, -			    uint16_t option_len, -			    const uint8_t *tlv_curr)  +			    uint16_t option_len, const uint8_t *tlv_curr)  { -  const uint8_t *addr; -  const uint8_t *pastend; - -  zassert(hello_option_addr_list); - -  /* -    Scan addr list -   */ -  addr = tlv_curr; -  pastend = tlv_curr + option_len; -  while (addr < pastend) { -    struct prefix tmp; -    int addr_offset; - -    /* -      Parse ucast addr -     */ -    addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); -    if (addr_offset < 1) { -      char src_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -      zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", -		__PRETTY_FUNCTION__, -		src_str, ifname); -      FREE_ADDR_LIST(*hello_option_addr_list); -      return -1; -    } -    addr += addr_offset; - -    /* -      Debug -     */ -    if (PIM_DEBUG_PIM_TRACE) { -      switch (tmp.family) { -      case AF_INET: -	{ -	  char addr_str[INET_ADDRSTRLEN]; -	  char src_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<addr?>", tmp.u.prefix4, addr_str, sizeof(addr_str)); -	  pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	  zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", -		     __PRETTY_FUNCTION__, -		     *hello_option_addr_list ? -		     ((int) listcount(*hello_option_addr_list)) : -1, -		     addr_str, src_str, ifname); -	} -	break; -      case AF_INET6: -        break; -      default: -	{ -	  char src_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	  zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", -		     __PRETTY_FUNCTION__, -		     *hello_option_addr_list ? -		     ((int) listcount(*hello_option_addr_list)) : -1, -		     src_str, ifname); -	} -      } -    } - -    /* -      Exclude neighbor's primary address if incorrectly included in -      the secondary address list -     */ -    if (tmp.family == AF_INET) { -      if (tmp.u.prefix4.s_addr == src_addr.s_addr) { -	  char src_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); -	  zlog_warn("%s: ignoring primary address in secondary list from %s on %s", -		    __PRETTY_FUNCTION__, -		    src_str, ifname); -	  continue; -      } -    } - -    /* -      Allocate list if needed -     */ -    if (!*hello_option_addr_list) { -      *hello_option_addr_list = list_new(); -      if (!*hello_option_addr_list) { -	zlog_err("%s %s: failure: hello_option_addr_list=list_new()", -		 __FILE__, __PRETTY_FUNCTION__); -	return -2; -      } -      (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free; -    } - -    /* -      Attach addr to list -     */ -    { -      struct prefix *p; -      p = prefix_new(); -      if (!p) { -	zlog_err("%s %s: failure: prefix_new()", -		 __FILE__, __PRETTY_FUNCTION__); -	FREE_ADDR_LIST(*hello_option_addr_list); -	return -3; -      } -      prefix_copy(p, &tmp); -      listnode_add(*hello_option_addr_list, p); -    } - -  } /* while (addr < pastend) */ -   -  /* -    Mark hello option -   */ -  PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST); -   -  return 0; +	const uint8_t *addr; +	const uint8_t *pastend; + +	zassert(hello_option_addr_list); + +	/* +	  Scan addr list +	 */ +	addr = tlv_curr; +	pastend = tlv_curr + option_len; +	while (addr < pastend) { +		struct prefix tmp; +		int addr_offset; + +		/* +		  Parse ucast addr +		 */ +		addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); +		if (addr_offset < 1) { +			char src_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<src?>", src_addr, src_str, +				       sizeof(src_str)); +			zlog_warn( +				"%s: pim_parse_addr_ucast() failure: from %s on %s", +				__PRETTY_FUNCTION__, src_str, ifname); +			FREE_ADDR_LIST(*hello_option_addr_list); +			return -1; +		} +		addr += addr_offset; + +		/* +		  Debug +		 */ +		if (PIM_DEBUG_PIM_TRACE) { +			switch (tmp.family) { +			case AF_INET: { +				char addr_str[INET_ADDRSTRLEN]; +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", tmp.u.prefix4, +					       addr_str, sizeof(addr_str)); +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_debug( +					"%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", +					__PRETTY_FUNCTION__, +					*hello_option_addr_list +						? ((int)listcount( +							  *hello_option_addr_list)) +						: -1, +					addr_str, src_str, ifname); +			} break; +			case AF_INET6: +				break; +			default: { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_debug( +					"%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", +					__PRETTY_FUNCTION__, +					*hello_option_addr_list +						? ((int)listcount( +							  *hello_option_addr_list)) +						: -1, +					src_str, ifname); +			} +			} +		} + +		/* +		  Exclude neighbor's primary address if incorrectly included in +		  the secondary address list +		 */ +		if (tmp.family == AF_INET) { +			if (tmp.u.prefix4.s_addr == src_addr.s_addr) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", src_addr, src_str, +					       sizeof(src_str)); +				zlog_warn( +					"%s: ignoring primary address in secondary list from %s on %s", +					__PRETTY_FUNCTION__, src_str, ifname); +				continue; +			} +		} + +		/* +		  Allocate list if needed +		 */ +		if (!*hello_option_addr_list) { +			*hello_option_addr_list = list_new(); +			if (!*hello_option_addr_list) { +				zlog_err( +					"%s %s: failure: hello_option_addr_list=list_new()", +					__FILE__, __PRETTY_FUNCTION__); +				return -2; +			} +			(*hello_option_addr_list)->del = +				(void (*)(void *))prefix_free; +		} + +		/* +		  Attach addr to list +		 */ +		{ +			struct prefix *p; +			p = prefix_new(); +			if (!p) { +				zlog_err("%s %s: failure: prefix_new()", +					 __FILE__, __PRETTY_FUNCTION__); +				FREE_ADDR_LIST(*hello_option_addr_list); +				return -3; +			} +			prefix_copy(p, &tmp); +			listnode_add(*hello_option_addr_list, p); +		} + +	} /* while (addr < pastend) */ + +	/* +	  Mark hello option +	 */ +	PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST); + +	return 0;  } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index f80e1fba27..657675b312 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -64,63 +64,46 @@ typedef uint32_t pim_hello_options;  #define PIM_TLV_MIN_SIZE                (PIM_TLV_TYPE_SIZE + PIM_TLV_LENGTH_SIZE)  #define PIM_TLV_OPTION_SIZE(option_len) (PIM_TLV_MIN_SIZE + (option_len)) -uint8_t *pim_tlv_append_uint16(uint8_t *buf, -			       const uint8_t *buf_pastend, -			       uint16_t option_type, -			       uint16_t option_value); -uint8_t *pim_tlv_append_2uint16(uint8_t *buf, -				const uint8_t *buf_pastend, -				uint16_t option_type, -				uint16_t option_value1, +uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend, +			       uint16_t option_type, uint16_t option_value); +uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend, +				uint16_t option_type, uint16_t option_value1,  				uint16_t option_value2); -uint8_t *pim_tlv_append_uint32(uint8_t *buf, -			       const uint8_t *buf_pastend, -			       uint16_t option_type, -			       uint32_t option_value); -uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, -				       const uint8_t *buf_pastend, -				       struct list *ifconnected, -                                       int family); +uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend, +			       uint16_t option_type, uint32_t option_value); +uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, +				       struct list *ifconnected, int family);  int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,  			   pim_hello_options *hello_options, -			   uint16_t *hello_option_holdtime, -			   uint16_t option_len, +			   uint16_t *hello_option_holdtime, uint16_t option_len,  			   const uint8_t *tlv_curr);  int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,  				  pim_hello_options *hello_options,  				  uint16_t *hello_option_propagation_delay,  				  uint16_t *hello_option_override_interval, -				  uint16_t option_len, -				  const uint8_t *tlv_curr); +				  uint16_t option_len, const uint8_t *tlv_curr);  int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,  			      pim_hello_options *hello_options,  			      uint32_t *hello_option_dr_priority, -			      uint16_t option_len, -			      const uint8_t *tlv_curr); +			      uint16_t option_len, const uint8_t *tlv_curr);  int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,  				pim_hello_options *hello_options,  				uint32_t *hello_option_generation_id, -				uint16_t option_len, -				const uint8_t *tlv_curr); +				uint16_t option_len, const uint8_t *tlv_curr);  int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,  			    pim_hello_options *hello_options,  			    struct list **hello_option_addr_list, -			    uint16_t option_len, -			    const uint8_t *tlv_curr); +			    uint16_t option_len, const uint8_t *tlv_curr); -int pim_encode_addr_ucast (uint8_t *buf, struct prefix *p); -int pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group); +int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p); +int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope, +			  struct in_addr group); -int pim_parse_addr_ucast (struct prefix *p, -			  const uint8_t *buf, -			  int buf_size); -int pim_parse_addr_group (struct prefix_sg *sg, -			  const uint8_t *buf, -			  int buf_size); -int pim_parse_addr_source(struct prefix_sg *sg, -			  uint8_t *flags, -			  const uint8_t *buf, -			  int buf_size); +int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size); +int pim_parse_addr_group(struct prefix_sg *sg, const uint8_t *buf, +			 int buf_size); +int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, +			  const uint8_t *buf, int buf_size);  #endif /* PIM_TLV_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 442cb02a15..0ddd04c38c 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -59,35 +59,33 @@ struct list *pim_upstream_list = NULL;  struct timer_wheel *pim_upstream_sg_wheel = NULL;  static void join_timer_stop(struct pim_upstream *up); -static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); +static void +pim_upstream_update_assert_tracking_desired(struct pim_upstream *up);  /*   * A (*,G) or a (*,*) is going away   * remove the parent pointer from   * those pointing at us   */ -static void -pim_upstream_remove_children (struct pim_upstream *up) +static void pim_upstream_remove_children(struct pim_upstream *up)  { -  struct pim_upstream *child; - -  if (!up->sources) -    return; - -  while (!list_isempty (up->sources)) -    { -      child = listnode_head (up->sources); -      listnode_delete (up->sources, child); -      if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) -        { -          PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); -          child = pim_upstream_del(child, __PRETTY_FUNCTION__); -        } -      if (child) -        child->parent = NULL; -    } -  list_delete(up->sources); -  up->sources = NULL; +	struct pim_upstream *child; + +	if (!up->sources) +		return; + +	while (!list_isempty(up->sources)) { +		child = listnode_head(up->sources); +		listnode_delete(up->sources, child); +		if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) { +			PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); +			child = pim_upstream_del(child, __PRETTY_FUNCTION__); +		} +		if (child) +			child->parent = NULL; +	} +	list_delete(up->sources); +	up->sources = NULL;  }  /* @@ -95,30 +93,27 @@ pim_upstream_remove_children (struct pim_upstream *up)   * Find the children that would point   * at us.   */ -static void -pim_upstream_find_new_children (struct pim_upstream *up) +static void pim_upstream_find_new_children(struct pim_upstream *up)  { -  struct pim_upstream *child; -  struct listnode *ch_node; - -  if ((up->sg.src.s_addr != INADDR_ANY) && -      (up->sg.grp.s_addr != INADDR_ANY)) -    return; - -  if ((up->sg.src.s_addr == INADDR_ANY) && -      (up->sg.grp.s_addr == INADDR_ANY)) -    return; - -  for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, ch_node, child)) -    { -      if ((up->sg.grp.s_addr != INADDR_ANY) && -	  (child->sg.grp.s_addr == up->sg.grp.s_addr) && -	  (child != up)) -	{ -	  child->parent = up; -	  listnode_add_sort (up->sources, child); +	struct pim_upstream *child; +	struct listnode *ch_node; + +	if ((up->sg.src.s_addr != INADDR_ANY) +	    && (up->sg.grp.s_addr != INADDR_ANY)) +		return; + +	if ((up->sg.src.s_addr == INADDR_ANY) +	    && (up->sg.grp.s_addr == INADDR_ANY)) +		return; + +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, ch_node, child)) { +		if ((up->sg.grp.s_addr != INADDR_ANY) +		    && (child->sg.grp.s_addr == up->sg.grp.s_addr) +		    && (child != up)) { +			child->parent = up; +			listnode_add_sort(up->sources, child); +		}  	} -    }  }  /* @@ -126,218 +121,211 @@ pim_upstream_find_new_children (struct pim_upstream *up)   * If we have a (S,G), find the (*,G)   * If we have a (*,G), find the (*,*)   */ -static struct pim_upstream * -pim_upstream_find_parent (struct pim_upstream *child) +static struct pim_upstream *pim_upstream_find_parent(struct pim_upstream *child)  { -  struct prefix_sg any = child->sg; -  struct pim_upstream *up = NULL; +	struct prefix_sg any = child->sg; +	struct pim_upstream *up = NULL; -  // (S,G) -  if ((child->sg.src.s_addr != INADDR_ANY) && -      (child->sg.grp.s_addr != INADDR_ANY)) -    { -      any.src.s_addr = INADDR_ANY; -      up = pim_upstream_find (&any); +	// (S,G) +	if ((child->sg.src.s_addr != INADDR_ANY) +	    && (child->sg.grp.s_addr != INADDR_ANY)) { +		any.src.s_addr = INADDR_ANY; +		up = pim_upstream_find(&any); -      if (up) -	listnode_add (up->sources, child); +		if (up) +			listnode_add(up->sources, child); -      return up; -    } +		return up; +	} -  return NULL; +	return NULL;  }  void pim_upstream_free(struct pim_upstream *up)  { -  XFREE(MTYPE_PIM_UPSTREAM, up); -  up = NULL; +	XFREE(MTYPE_PIM_UPSTREAM, up); +	up = NULL;  }  static void upstream_channel_oil_detach(struct pim_upstream *up)  { -  if (up->channel_oil) -    { -      /* Detaching from channel_oil, channel_oil may exist post del, -         but upstream would not keep reference of it -       */ -      pim_channel_oil_del(up->channel_oil); -      up->channel_oil = NULL; -    } +	if (up->channel_oil) { +		/* Detaching from channel_oil, channel_oil may exist post del, +		   but upstream would not keep reference of it +		 */ +		pim_channel_oil_del(up->channel_oil); +		up->channel_oil = NULL; +	}  } -struct pim_upstream * -pim_upstream_del(struct pim_upstream *up, const char *name) +struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name)  { -  bool notify_msdp = false; -  struct prefix nht_p; - -  if (PIM_DEBUG_TRACE) -    zlog_debug ("%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", -                __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags, -                up->channel_oil->oil_ref_count); - -  --up->ref_count; - -  if (up->ref_count >= 1) -    return up; - -  THREAD_OFF(up->t_ka_timer); -  THREAD_OFF(up->t_rs_timer); -  THREAD_OFF(up->t_msdp_reg_timer); - -  if (up->join_state == PIM_UPSTREAM_JOINED) { -    pim_jp_agg_single_upstream_send (&up->rpf, up, 0); - -    if (up->sg.src.s_addr == INADDR_ANY) { -        /* if a (*, G) entry in the joined state is being deleted we -         * need to notify MSDP */ -        notify_msdp = true; -    } -  } - -  join_timer_stop(up); -  pim_jp_agg_upstream_verification (up, false); -  up->rpf.source_nexthop.interface = NULL; - -  if (up->sg.src.s_addr != INADDR_ANY) { -    wheel_remove_item (pim_upstream_sg_wheel, up); -    notify_msdp = true; -  } - -  pim_upstream_remove_children (up); -  if (up->sources) -    list_delete (up->sources); -  up->sources = NULL; -  pim_mroute_del (up->channel_oil, __PRETTY_FUNCTION__); -  upstream_channel_oil_detach(up); - -  list_delete (up->ifchannels); -  up->ifchannels = NULL; - -  /* -    notice that listnode_delete() can't be moved -    into pim_upstream_free() because the later is -    called by list_delete_all_node() -  */ -  if (up->parent && up->parent->sources) -    listnode_delete (up->parent->sources, up); -  up->parent = NULL; - -  listnode_delete (pim_upstream_list, up); -  hash_release (pim_upstream_hash, up); - -  if (notify_msdp) -    { -      pim_msdp_up_del (&up->sg); -    } - -  /* Deregister addr with Zebra NHT */ -  nht_p.family = AF_INET; -  nht_p.prefixlen = IPV4_MAX_BITLEN; -  nht_p.u.prefix4 = up->upstream_addr; -  if (PIM_DEBUG_TRACE) -    { -      char buf[PREFIX2STR_BUFFER]; -      prefix2str (&nht_p, buf, sizeof (buf)); -      zlog_debug ("%s: Deregister upstream %s addr %s with Zebra NHT", -                  __PRETTY_FUNCTION__, up->sg_str, buf); -    } -  pim_delete_tracked_nexthop (&nht_p, up, NULL); - -  pim_upstream_free (up); - -  return NULL; +	bool notify_msdp = false; +	struct prefix nht_p; + +	if (PIM_DEBUG_TRACE) +		zlog_debug( +			"%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", +			__PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, +			up->flags, up->channel_oil->oil_ref_count); + +	--up->ref_count; + +	if (up->ref_count >= 1) +		return up; + +	THREAD_OFF(up->t_ka_timer); +	THREAD_OFF(up->t_rs_timer); +	THREAD_OFF(up->t_msdp_reg_timer); + +	if (up->join_state == PIM_UPSTREAM_JOINED) { +		pim_jp_agg_single_upstream_send(&up->rpf, up, 0); + +		if (up->sg.src.s_addr == INADDR_ANY) { +			/* if a (*, G) entry in the joined state is being +			 * deleted we +			 * need to notify MSDP */ +			notify_msdp = true; +		} +	} + +	join_timer_stop(up); +	pim_jp_agg_upstream_verification(up, false); +	up->rpf.source_nexthop.interface = NULL; + +	if (up->sg.src.s_addr != INADDR_ANY) { +		wheel_remove_item(pim_upstream_sg_wheel, up); +		notify_msdp = true; +	} + +	pim_upstream_remove_children(up); +	if (up->sources) +		list_delete(up->sources); +	up->sources = NULL; +	pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__); +	upstream_channel_oil_detach(up); + +	list_delete(up->ifchannels); +	up->ifchannels = NULL; + +	/* +	  notice that listnode_delete() can't be moved +	  into pim_upstream_free() because the later is +	  called by list_delete_all_node() +	*/ +	if (up->parent && up->parent->sources) +		listnode_delete(up->parent->sources, up); +	up->parent = NULL; + +	listnode_delete(pim_upstream_list, up); +	hash_release(pim_upstream_hash, up); + +	if (notify_msdp) { +		pim_msdp_up_del(&up->sg); +	} + +	/* Deregister addr with Zebra NHT */ +	nht_p.family = AF_INET; +	nht_p.prefixlen = IPV4_MAX_BITLEN; +	nht_p.u.prefix4 = up->upstream_addr; +	if (PIM_DEBUG_TRACE) { +		char buf[PREFIX2STR_BUFFER]; +		prefix2str(&nht_p, buf, sizeof(buf)); +		zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT", +			   __PRETTY_FUNCTION__, up->sg_str, buf); +	} +	pim_delete_tracked_nexthop(&nht_p, up, NULL); + +	pim_upstream_free(up); + +	return NULL;  } -void -pim_upstream_send_join (struct pim_upstream *up) +void pim_upstream_send_join(struct pim_upstream *up)  { -  if (PIM_DEBUG_TRACE) { -    char rpf_str[PREFIX_STRLEN]; -    pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); -    zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, -		up->sg_str, rpf_str, pim_upstream_state2str (up->join_state), -		up->rpf.source_nexthop.interface->name); -    if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { -      zlog_debug("%s: can't send join upstream: RPF'%s=%s", -		 __PRETTY_FUNCTION__, -		 up->sg_str, rpf_str); -      /* warning only */ -    } -  } - -  /* send Join(S,G) to the current upstream neighbor */ -  pim_jp_agg_single_upstream_send(&up->rpf, up, 1 /* join */); +	if (PIM_DEBUG_TRACE) { +		char rpf_str[PREFIX_STRLEN]; +		pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str, +			      sizeof(rpf_str)); +		zlog_debug("%s: RPF'%s=%s(%s) for Interface %s", +			   __PRETTY_FUNCTION__, up->sg_str, rpf_str, +			   pim_upstream_state2str(up->join_state), +			   up->rpf.source_nexthop.interface->name); +		if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { +			zlog_debug("%s: can't send join upstream: RPF'%s=%s", +				   __PRETTY_FUNCTION__, up->sg_str, rpf_str); +			/* warning only */ +		} +	} + +	/* send Join(S,G) to the current upstream neighbor */ +	pim_jp_agg_single_upstream_send(&up->rpf, up, 1 /* join */);  }  static int on_join_timer(struct thread *t)  { -  struct pim_upstream *up; +	struct pim_upstream *up; -  up = THREAD_ARG(t); +	up = THREAD_ARG(t); -  /* -   * In the case of a HFR we will not ahve anyone to send this to. -   */ -  if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) -    return 0; +	/* +	 * In the case of a HFR we will not ahve anyone to send this to. +	 */ +	if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) +		return 0; -  /* -   * Don't send the join if the outgoing interface is a loopback -   * But since this might change leave the join timer running -   */ -  if (up->rpf.source_nexthop.interface && -      !if_is_loopback (up->rpf.source_nexthop.interface)) -    pim_upstream_send_join (up); +	/* +	 * Don't send the join if the outgoing interface is a loopback +	 * But since this might change leave the join timer running +	 */ +	if (up->rpf.source_nexthop +		    .interface && !if_is_loopback(up->rpf.source_nexthop.interface)) +		pim_upstream_send_join(up); -  join_timer_start(up); +	join_timer_start(up); -  return 0; +	return 0;  }  static void join_timer_stop(struct pim_upstream *up)  { -  struct pim_neighbor *nbr; +	struct pim_neighbor *nbr; -  THREAD_OFF (up->t_join_timer); +	THREAD_OFF(up->t_join_timer); -  nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, -                           up->rpf.rpf_addr.u.prefix4); +	nbr = pim_neighbor_find(up->rpf.source_nexthop.interface, +				up->rpf.rpf_addr.u.prefix4); -  if (nbr) -    pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); +	if (nbr) +		pim_jp_agg_remove_group(nbr->upstream_jp_agg, up); -  pim_jp_agg_upstream_verification (up, false); +	pim_jp_agg_upstream_verification(up, false);  } -void -join_timer_start(struct pim_upstream *up) +void join_timer_start(struct pim_upstream *up)  { -  struct pim_neighbor *nbr = NULL; - -  if (up->rpf.source_nexthop.interface) -    { -      nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, -                               up->rpf.rpf_addr.u.prefix4); - -      if (PIM_DEBUG_PIM_EVENTS) { -        zlog_debug("%s: starting %d sec timer for upstream (S,G)=%s", -                   __PRETTY_FUNCTION__, -                   qpim_t_periodic, -                   up->sg_str); -      } -    } - -  if (nbr) -    pim_jp_agg_add_group (nbr->upstream_jp_agg, up, 1); -  else -    { -      THREAD_OFF (up->t_join_timer); -      thread_add_timer(master, on_join_timer, up, qpim_t_periodic, -                       &up->t_join_timer); -    } -  pim_jp_agg_upstream_verification (up, true); +	struct pim_neighbor *nbr = NULL; + +	if (up->rpf.source_nexthop.interface) { +		nbr = pim_neighbor_find(up->rpf.source_nexthop.interface, +					up->rpf.rpf_addr.u.prefix4); + +		if (PIM_DEBUG_PIM_EVENTS) { +			zlog_debug( +				"%s: starting %d sec timer for upstream (S,G)=%s", +				__PRETTY_FUNCTION__, qpim_t_periodic, +				up->sg_str); +		} +	} + +	if (nbr) +		pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1); +	else { +		THREAD_OFF(up->t_join_timer); +		thread_add_timer(master, on_join_timer, up, qpim_t_periodic, +				 &up->t_join_timer); +	} +	pim_jp_agg_upstream_verification(up, true);  }  /* @@ -347,501 +335,488 @@ join_timer_start(struct pim_upstream *up)   * As such we need to remove from the old list and   * add to the new list.   */ -void pim_upstream_join_timer_restart(struct pim_upstream *up, struct pim_rpf *old) +void pim_upstream_join_timer_restart(struct pim_upstream *up, +				     struct pim_rpf *old)  { -  //THREAD_OFF(up->t_join_timer); -  join_timer_start(up); +	// THREAD_OFF(up->t_join_timer); +	join_timer_start(up);  }  static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up,  						 int interval_msec)  { -  if (PIM_DEBUG_PIM_EVENTS) { -    zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", -	       __PRETTY_FUNCTION__, -	       interval_msec, -	       up->sg_str); -  } - -  THREAD_OFF(up->t_join_timer); -  thread_add_timer_msec(master, on_join_timer, up, interval_msec, -                        &up->t_join_timer); +	if (PIM_DEBUG_PIM_EVENTS) { +		zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", +			   __PRETTY_FUNCTION__, interval_msec, up->sg_str); +	} + +	THREAD_OFF(up->t_join_timer); +	thread_add_timer_msec(master, on_join_timer, up, interval_msec, +			      &up->t_join_timer);  }  void pim_upstream_join_suppress(struct pim_upstream *up, -				struct in_addr rpf_addr, -				int holdtime) +				struct in_addr rpf_addr, int holdtime)  { -  long t_joinsuppress_msec; -  long join_timer_remain_msec; - -  t_joinsuppress_msec = MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface), -			    1000 * holdtime); - -  join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); - -  if (PIM_DEBUG_TRACE) { -    char rpf_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str)); -    zlog_debug("%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", -	       __FILE__, __PRETTY_FUNCTION__,  -	       up->sg_str, -	       rpf_str, -	       join_timer_remain_msec, t_joinsuppress_msec); -  } - -  if (join_timer_remain_msec < t_joinsuppress_msec) { -    if (PIM_DEBUG_TRACE) { -      zlog_debug("%s %s: suppressing Join(S,G)=%s for %ld msec", -		 __FILE__, __PRETTY_FUNCTION__,  -		 up->sg_str, t_joinsuppress_msec); -    } - -    pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); -  } +	long t_joinsuppress_msec; +	long join_timer_remain_msec; + +	t_joinsuppress_msec = +		MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface), +		    1000 * holdtime); + +	join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); + +	if (PIM_DEBUG_TRACE) { +		char rpf_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str)); +		zlog_debug( +			"%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", +			__FILE__, __PRETTY_FUNCTION__, up->sg_str, rpf_str, +			join_timer_remain_msec, t_joinsuppress_msec); +	} + +	if (join_timer_remain_msec < t_joinsuppress_msec) { +		if (PIM_DEBUG_TRACE) { +			zlog_debug( +				"%s %s: suppressing Join(S,G)=%s for %ld msec", +				__FILE__, __PRETTY_FUNCTION__, up->sg_str, +				t_joinsuppress_msec); +		} + +		pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); +	}  }  void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, -                                                    struct pim_upstream *up) +						    struct pim_upstream *up)  { -  long join_timer_remain_msec; -  int t_override_msec; - -  join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); -  t_override_msec = pim_if_t_override_msec(up->rpf.source_nexthop.interface); - -  if (PIM_DEBUG_TRACE) { -    char rpf_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<rpf?>", up->rpf.rpf_addr.u.prefix4, rpf_str, sizeof(rpf_str)); -    zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", -	       debug_label, -	       up->sg_str, rpf_str, -	       join_timer_remain_msec, t_override_msec); -  } -     -  if (join_timer_remain_msec > t_override_msec) { -    if (PIM_DEBUG_TRACE) { -      zlog_debug("%s: decreasing (S,G)=%s join timer to t_override=%d msec", -		 debug_label, -		 up->sg_str, -		 t_override_msec); -    } - -    pim_upstream_join_timer_restart_msec(up, t_override_msec); -  } +	long join_timer_remain_msec; +	int t_override_msec; + +	join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); +	t_override_msec = +		pim_if_t_override_msec(up->rpf.source_nexthop.interface); + +	if (PIM_DEBUG_TRACE) { +		char rpf_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<rpf?>", up->rpf.rpf_addr.u.prefix4, rpf_str, +			       sizeof(rpf_str)); +		zlog_debug( +			"%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", +			debug_label, up->sg_str, rpf_str, +			join_timer_remain_msec, t_override_msec); +	} + +	if (join_timer_remain_msec > t_override_msec) { +		if (PIM_DEBUG_TRACE) { +			zlog_debug( +				"%s: decreasing (S,G)=%s join timer to t_override=%d msec", +				debug_label, up->sg_str, t_override_msec); +		} + +		pim_upstream_join_timer_restart_msec(up, t_override_msec); +	}  }  static void forward_on(struct pim_upstream *up)  { -  struct listnode      *chnode; -  struct listnode      *chnextnode; -  struct pim_ifchannel *ch = NULL; +	struct listnode *chnode; +	struct listnode *chnextnode; +	struct pim_ifchannel *ch = NULL; -  /* scan (S,G) state */ -  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { -    if (pim_macro_chisin_oiflist(ch)) -      pim_forward_start(ch); +	/* scan (S,G) state */ +	for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { +		if (pim_macro_chisin_oiflist(ch)) +			pim_forward_start(ch); -  } /* scan iface channel list */ +	} /* scan iface channel list */  }  static void forward_off(struct pim_upstream *up)  { -  struct listnode      *chnode; -  struct listnode      *chnextnode; -  struct pim_ifchannel *ch; +	struct listnode *chnode; +	struct listnode *chnextnode; +	struct pim_ifchannel *ch; -  /* scan per-interface (S,G) state */ -  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { +	/* scan per-interface (S,G) state */ +	for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { -    pim_forward_stop(ch); +		pim_forward_stop(ch); -  } /* scan iface channel list */ +	} /* scan iface channel list */  } -static int -pim_upstream_could_register (struct pim_upstream *up) +static int pim_upstream_could_register(struct pim_upstream *up)  { -  struct pim_interface *pim_ifp = NULL; - -  if (up->rpf.source_nexthop.interface) -    pim_ifp = up->rpf.source_nexthop.interface->info; -  else -    { -      if (PIM_DEBUG_TRACE) -        zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str); -    } +	struct pim_interface *pim_ifp = NULL; + +	if (up->rpf.source_nexthop.interface) +		pim_ifp = up->rpf.source_nexthop.interface->info; +	else { +		if (PIM_DEBUG_TRACE) +			zlog_debug("%s: up %s RPF is not present", +				   __PRETTY_FUNCTION__, up->sg_str); +	} -  if (pim_ifp && PIM_I_am_DR (pim_ifp) && -      pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) -    return 1; +	if (pim_ifp && PIM_I_am_DR(pim_ifp) +	    && pim_if_connected_to_source(up->rpf.source_nexthop.interface, +					  up->sg.src)) +		return 1; -  return 0; +	return 0;  }  /* Source registration is supressed for SSM groups. When the SSM range changes   * we re-revaluate register setup for existing upstream entries */ -void -pim_upstream_register_reevaluate (void) +void pim_upstream_register_reevaluate(void)  { -  struct listnode *upnode; -  struct pim_upstream *up; - -  for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, upnode, up)) -    { -      /* If FHR is set CouldRegister is True. Also check if the flow -       * is actually active; if it is not kat setup will trigger source -       * registration whenever the flow becomes active. */ -      if (!PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) || !up->t_ka_timer) -        continue; - -      if (pim_is_grp_ssm (up->sg.grp)) -        { -          /* clear the register state  for SSM groups */ -          if (up->reg_state != PIM_REG_NOINFO) -            { -              if (PIM_DEBUG_PIM_EVENTS) -                zlog_debug ("Clear register for %s as G is now SSM", -                            up->sg_str); -              /* remove regiface from the OIL if it is there*/ -              pim_channel_del_oif (up->channel_oil, pim_regiface, -                                   PIM_OIF_FLAG_PROTO_PIM); -              up->reg_state = PIM_REG_NOINFO; -            } -        } -      else -        { -          /* register ASM sources with the RP */ -          if (up->reg_state == PIM_REG_NOINFO) -            { -              if (PIM_DEBUG_PIM_EVENTS) -                zlog_debug ("Register %s as G is now ASM", up->sg_str); -              pim_channel_add_oif (up->channel_oil, pim_regiface, -                                   PIM_OIF_FLAG_PROTO_PIM); -              up->reg_state = PIM_REG_JOIN; -            } -        } -    } +	struct listnode *upnode; +	struct pim_upstream *up; + +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { +		/* If FHR is set CouldRegister is True. Also check if the flow +		 * is actually active; if it is not kat setup will trigger +		 * source +		 * registration whenever the flow becomes active. */ +		if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || !up->t_ka_timer) +			continue; + +		if (pim_is_grp_ssm(up->sg.grp)) { +			/* clear the register state  for SSM groups */ +			if (up->reg_state != PIM_REG_NOINFO) { +				if (PIM_DEBUG_PIM_EVENTS) +					zlog_debug( +						"Clear register for %s as G is now SSM", +						up->sg_str); +				/* remove regiface from the OIL if it is there*/ +				pim_channel_del_oif(up->channel_oil, +						    pim_regiface, +						    PIM_OIF_FLAG_PROTO_PIM); +				up->reg_state = PIM_REG_NOINFO; +			} +		} else { +			/* register ASM sources with the RP */ +			if (up->reg_state == PIM_REG_NOINFO) { +				if (PIM_DEBUG_PIM_EVENTS) +					zlog_debug( +						"Register %s as G is now ASM", +						up->sg_str); +				pim_channel_add_oif(up->channel_oil, +						    pim_regiface, +						    PIM_OIF_FLAG_PROTO_PIM); +				up->reg_state = PIM_REG_JOIN; +			} +		} +	}  } -void -pim_upstream_switch(struct pim_upstream *up, -		    enum pim_upstream_state new_state) +void pim_upstream_switch(struct pim_upstream *up, +			 enum pim_upstream_state new_state)  { -  enum pim_upstream_state old_state = up->join_state; - -  if (PIM_DEBUG_PIM_EVENTS) -    { -      zlog_debug ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", -	       __PRETTY_FUNCTION__, -	       up->sg_str, -	       pim_upstream_state2str (up->join_state), -	       pim_upstream_state2str (new_state)); -    } - -  up->join_state = new_state; -  if (old_state != new_state) -    up->state_transition = pim_time_monotonic_sec(); - -  pim_upstream_update_assert_tracking_desired(up); - -  if (new_state == PIM_UPSTREAM_JOINED) { -    if (old_state != PIM_UPSTREAM_JOINED) -      { -        int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags); -        forward_on(up); -        pim_msdp_up_join_state_changed(up); -	if (pim_upstream_could_register (up)) -	  { -            PIM_UPSTREAM_FLAG_SET_FHR(up->flags); -            if (!old_fhr && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) -              { -                pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); -                pim_register_join (up); -              } -	  } -	else -          { -	    pim_upstream_send_join (up); -	    join_timer_start (up); -	  } -      } -    else -      { -        forward_on (up); -      } -  } -  else { - -    forward_off(up); -    if (old_state == PIM_UPSTREAM_JOINED) -      pim_msdp_up_join_state_changed(up); - -    /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards RP. -       If I am RP for G then send S,G prune to its IIF. */ -    if (pim_upstream_is_sg_rpt(up) && up->parent && !I_am_RP(up->sg.grp)) -      { -        if (PIM_DEBUG_PIM_TRACE_DETAIL) -          zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__, -                    up->parent->rpf.source_nexthop.interface->name, -                    up->rpf.source_nexthop.interface->name); -        pim_jp_agg_single_upstream_send(&up->parent->rpf, up->parent, 1 /* (W,G) Join */); -      } -    else -      pim_jp_agg_single_upstream_send(&up->rpf, up, 0 /* prune */); -    join_timer_stop(up); -  } +	enum pim_upstream_state old_state = up->join_state; + +	if (PIM_DEBUG_PIM_EVENTS) { +		zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", +			   __PRETTY_FUNCTION__, up->sg_str, +			   pim_upstream_state2str(up->join_state), +			   pim_upstream_state2str(new_state)); +	} + +	up->join_state = new_state; +	if (old_state != new_state) +		up->state_transition = pim_time_monotonic_sec(); + +	pim_upstream_update_assert_tracking_desired(up); + +	if (new_state == PIM_UPSTREAM_JOINED) { +		if (old_state != PIM_UPSTREAM_JOINED) { +			int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags); +			forward_on(up); +			pim_msdp_up_join_state_changed(up); +			if (pim_upstream_could_register(up)) { +				PIM_UPSTREAM_FLAG_SET_FHR(up->flags); +				if (!old_fhr +				    && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM( +					       up->flags)) { +					pim_upstream_keep_alive_timer_start( +						up, qpim_keep_alive_time); +					pim_register_join(up); +				} +			} else { +				pim_upstream_send_join(up); +				join_timer_start(up); +			} +		} else { +			forward_on(up); +		} +	} else { + +		forward_off(up); +		if (old_state == PIM_UPSTREAM_JOINED) +			pim_msdp_up_join_state_changed(up); + +		/* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards +		   RP. +		   If I am RP for G then send S,G prune to its IIF. */ +		if (pim_upstream_is_sg_rpt(up) && up->parent +		    && !I_am_RP(up->sg.grp)) { +			if (PIM_DEBUG_PIM_TRACE_DETAIL) +				zlog_debug( +					"%s: *,G IIF %s S,G IIF %s ", +					__PRETTY_FUNCTION__, +					up->parent->rpf.source_nexthop +						.interface->name, +					up->rpf.source_nexthop.interface->name); +			pim_jp_agg_single_upstream_send(&up->parent->rpf, +							up->parent, +							1 /* (W,G) Join */); +		} else +			pim_jp_agg_single_upstream_send(&up->rpf, up, +							0 /* prune */); +		join_timer_stop(up); +	}  } -int -pim_upstream_compare (void *arg1, void *arg2) +int pim_upstream_compare(void *arg1, void *arg2)  { -  const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; -  const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; +	const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; +	const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; -  if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) -    return -1; +	if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) +		return -1; -  if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) -    return 1; +	if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) +		return 1; -  if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) -    return -1; +	if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) +		return -1; -  if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) -    return 1; +	if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) +		return 1; -  return 0; +	return 0;  }  static struct pim_upstream * -pim_upstream_new (struct prefix_sg *sg, -		  struct interface *incoming, -		  int flags) +pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)  { -  enum pim_rpf_result rpf_result; -  struct pim_interface *pim_ifp; -  struct pim_upstream *up; - -  up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); -  if (!up) -    { -      zlog_err("%s: PIM XCALLOC(%zu) failure", -	     __PRETTY_FUNCTION__, sizeof(*up)); -      return NULL; -    } -   -  up->sg                          = *sg; -  pim_str_sg_set (sg, up->sg_str); -  up = hash_get (pim_upstream_hash, up, hash_alloc_intern); -  if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src, sg->grp)) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); - -      hash_release (pim_upstream_hash, up); -      XFREE (MTYPE_PIM_UPSTREAM, up); -      return NULL; -    } - -  up->parent                     = pim_upstream_find_parent (up); -  if (up->sg.src.s_addr == INADDR_ANY) -    { -      up->sources = list_new (); -      up->sources->cmp = pim_upstream_compare; -    } -  else -    up->sources = NULL; - -  pim_upstream_find_new_children (up); -  up->flags                      = flags; -  up->ref_count                  = 1; -  up->t_join_timer               = NULL; -  up->t_ka_timer                 = NULL; -  up->t_rs_timer                 = NULL; -  up->t_msdp_reg_timer           = NULL; -  up->join_state                 = PIM_UPSTREAM_NOTJOINED; -  up->reg_state                  = PIM_REG_NOINFO; -  up->state_transition           = pim_time_monotonic_sec(); -  up->channel_oil                = NULL; -  up->sptbit                     = PIM_UPSTREAM_SPTBIT_FALSE; - -  up->rpf.source_nexthop.interface                = NULL; -  up->rpf.source_nexthop.mrib_nexthop_addr.family = AF_INET; -  up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; -  up->rpf.source_nexthop.mrib_metric_preference   = qpim_infinite_assert_metric.metric_preference; -  up->rpf.source_nexthop.mrib_route_metric        = qpim_infinite_assert_metric.route_metric; -  up->rpf.rpf_addr.family                         = AF_INET; -  up->rpf.rpf_addr.u.prefix4.s_addr               = PIM_NET_INADDR_ANY; - -  up->ifchannels                 = list_new(); -  up->ifchannels->cmp            = (int (*)(void *, void *))pim_ifchannel_compare; - -  if (up->sg.src.s_addr != INADDR_ANY) -    wheel_add_item (pim_upstream_sg_wheel, up); - -  rpf_result = pim_rpf_update(up, NULL, 1); -  if (rpf_result == PIM_RPF_FAILURE) { -    struct prefix nht_p; - -    if (PIM_DEBUG_TRACE) -      zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, -                  up->sg_str); - -    nht_p.family = AF_INET; -    nht_p.prefixlen = IPV4_MAX_BITLEN; -    nht_p.u.prefix4 = up->upstream_addr; -    pim_delete_tracked_nexthop (&nht_p, up, NULL); - -    if (up->parent) -      { -	listnode_delete (up->parent->sources, up); -	up->parent = NULL; -      } - -    if (up->sg.src.s_addr != INADDR_ANY) -      wheel_remove_item (pim_upstream_sg_wheel, up); - -    pim_upstream_remove_children (up); -    if (up->sources) -      list_delete (up->sources); - -    hash_release (pim_upstream_hash, up); -    XFREE(MTYPE_PIM_UPSTREAM, up); -    return NULL; -  } - -  if (up->rpf.source_nexthop.interface) -    { -      pim_ifp = up->rpf.source_nexthop.interface->info; -      if (pim_ifp) -        up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index); -    } -  listnode_add_sort(pim_upstream_list, up); - -  if (PIM_DEBUG_TRACE) -    { -      zlog_debug ("%s: Created Upstream %s upstream_addr %s ref count %d increment", -            __PRETTY_FUNCTION__, up->sg_str, -            inet_ntoa (up->upstream_addr), up->ref_count); -    } - -  return up; +	enum pim_rpf_result rpf_result; +	struct pim_interface *pim_ifp; +	struct pim_upstream *up; + +	up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); +	if (!up) { +		zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, +			 sizeof(*up)); +		return NULL; +	} + +	up->sg = *sg; +	pim_str_sg_set(sg, up->sg_str); +	up = hash_get(pim_upstream_hash, up, hash_alloc_intern); +	if (!pim_rp_set_upstream_addr(&up->upstream_addr, sg->src, sg->grp)) { +		if (PIM_DEBUG_TRACE) +			zlog_debug("%s: Received a (*,G) with no RP configured", +				   __PRETTY_FUNCTION__); + +		hash_release(pim_upstream_hash, up); +		XFREE(MTYPE_PIM_UPSTREAM, up); +		return NULL; +	} + +	up->parent = pim_upstream_find_parent(up); +	if (up->sg.src.s_addr == INADDR_ANY) { +		up->sources = list_new(); +		up->sources->cmp = pim_upstream_compare; +	} else +		up->sources = NULL; + +	pim_upstream_find_new_children(up); +	up->flags = flags; +	up->ref_count = 1; +	up->t_join_timer = NULL; +	up->t_ka_timer = NULL; +	up->t_rs_timer = NULL; +	up->t_msdp_reg_timer = NULL; +	up->join_state = PIM_UPSTREAM_NOTJOINED; +	up->reg_state = PIM_REG_NOINFO; +	up->state_transition = pim_time_monotonic_sec(); +	up->channel_oil = NULL; +	up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; + +	up->rpf.source_nexthop.interface = NULL; +	up->rpf.source_nexthop.mrib_nexthop_addr.family = AF_INET; +	up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = +		PIM_NET_INADDR_ANY; +	up->rpf.source_nexthop.mrib_metric_preference = +		qpim_infinite_assert_metric.metric_preference; +	up->rpf.source_nexthop.mrib_route_metric = +		qpim_infinite_assert_metric.route_metric; +	up->rpf.rpf_addr.family = AF_INET; +	up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; + +	up->ifchannels = list_new(); +	up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare; + +	if (up->sg.src.s_addr != INADDR_ANY) +		wheel_add_item(pim_upstream_sg_wheel, up); + +	rpf_result = pim_rpf_update(up, NULL, 1); +	if (rpf_result == PIM_RPF_FAILURE) { +		struct prefix nht_p; + +		if (PIM_DEBUG_TRACE) +			zlog_debug( +				"%s: Attempting to create upstream(%s), Unable to RPF for source", +				__PRETTY_FUNCTION__, up->sg_str); + +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4 = up->upstream_addr; +		pim_delete_tracked_nexthop(&nht_p, up, NULL); + +		if (up->parent) { +			listnode_delete(up->parent->sources, up); +			up->parent = NULL; +		} + +		if (up->sg.src.s_addr != INADDR_ANY) +			wheel_remove_item(pim_upstream_sg_wheel, up); + +		pim_upstream_remove_children(up); +		if (up->sources) +			list_delete(up->sources); + +		hash_release(pim_upstream_hash, up); +		XFREE(MTYPE_PIM_UPSTREAM, up); +		return NULL; +	} + +	if (up->rpf.source_nexthop.interface) { +		pim_ifp = up->rpf.source_nexthop.interface->info; +		if (pim_ifp) +			up->channel_oil = pim_channel_oil_add( +				&up->sg, pim_ifp->mroute_vif_index); +	} +	listnode_add_sort(pim_upstream_list, up); + +	if (PIM_DEBUG_TRACE) { +		zlog_debug( +			"%s: Created Upstream %s upstream_addr %s ref count %d increment", +			__PRETTY_FUNCTION__, up->sg_str, +			inet_ntoa(up->upstream_addr), up->ref_count); +	} + +	return up;  }  struct pim_upstream *pim_upstream_find(struct prefix_sg *sg)  { -  struct pim_upstream lookup; -  struct pim_upstream *up = NULL; +	struct pim_upstream lookup; +	struct pim_upstream *up = NULL; -  lookup.sg = *sg; -  up = hash_lookup (pim_upstream_hash, &lookup); -  return up; +	lookup.sg = *sg; +	up = hash_lookup(pim_upstream_hash, &lookup); +	return up;  } -struct pim_upstream * -pim_upstream_find_or_add(struct prefix_sg *sg, -                         struct interface *incoming, -                         int flags, const char *name) +struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, +					      struct interface *incoming, +					      int flags, const char *name)  { -  struct pim_upstream *up; - -  up = pim_upstream_find(sg); - -  if (up) -    { -      if (!(up->flags & flags)) -        { -          up->flags |= flags; -          up->ref_count++; -          if (PIM_DEBUG_TRACE) -            zlog_debug ("%s(%s): upstream %s ref count %d increment", -                  __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); -        } -    } -  else -    up = pim_upstream_add (sg, incoming, flags, name); - -  return up; +	struct pim_upstream *up; + +	up = pim_upstream_find(sg); + +	if (up) { +		if (!(up->flags & flags)) { +			up->flags |= flags; +			up->ref_count++; +			if (PIM_DEBUG_TRACE) +				zlog_debug( +					"%s(%s): upstream %s ref count %d increment", +					__PRETTY_FUNCTION__, name, up->sg_str, +					up->ref_count); +		} +	} else +		up = pim_upstream_add(sg, incoming, flags, name); + +	return up;  } -void -pim_upstream_ref(struct pim_upstream *up, int flags, const char *name) +void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)  { -  up->flags |= flags; -  ++up->ref_count; -  if (PIM_DEBUG_TRACE) -    zlog_debug ("%s(%s): upstream %s ref count %d increment", -              __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); +	up->flags |= flags; +	++up->ref_count; +	if (PIM_DEBUG_TRACE) +		zlog_debug("%s(%s): upstream %s ref count %d increment", +			   __PRETTY_FUNCTION__, name, up->sg_str, +			   up->ref_count);  }  struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, -				      struct interface *incoming, -				      int flags, const char *name) +				      struct interface *incoming, int flags, +				      const char *name)  { -  struct pim_upstream *up = NULL; -  int found = 0; -  up = pim_upstream_find(sg); -  if (up) { -    pim_upstream_ref(up, flags, name); -    found = 1; -  } -  else { -    up = pim_upstream_new(sg, incoming, flags); -  } - -  if (PIM_DEBUG_TRACE) -    { -      if (up) -        { -          char buf[PREFIX2STR_BUFFER]; -          prefix2str (&up->rpf.rpf_addr, buf, sizeof (buf)); -	  zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d", +	struct pim_upstream *up = NULL; +	int found = 0; +	up = pim_upstream_find(sg); +	if (up) { +		pim_upstream_ref(up, flags, name); +		found = 1; +	} else { +		up = pim_upstream_new(sg, incoming, flags); +	} + +	if (PIM_DEBUG_TRACE) { +		if (up) { +			char buf[PREFIX2STR_BUFFER]; +			prefix2str(&up->rpf.rpf_addr, buf, sizeof(buf)); +			zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d",  		   __PRETTY_FUNCTION__, name,  		   up->sg_str, buf, up->rpf.source_nexthop.interface ?                     up->rpf.source_nexthop.interface->name : "NIL" ,  		   found, up->ref_count); -        } -      else -	zlog_debug("%s(%s): (%s) failure to create", -		   __PRETTY_FUNCTION__, name, -		   pim_str_sg_dump (sg)); -    } +		} else +			zlog_debug("%s(%s): (%s) failure to create", +				   __PRETTY_FUNCTION__, name, +				   pim_str_sg_dump(sg)); +	} -  return up; +	return up;  }  /*   * Passed in up must be the upstream for ch.  starch is NULL if no   * information   */ -int -pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, -                                              struct pim_ifchannel *ch, -                                              struct pim_ifchannel *starch) +int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up, +						 struct pim_ifchannel *ch, +						 struct pim_ifchannel *starch)  { -  if (ch) -    { -      if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) -        return 0; - -      if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch)) -        return 1; -    } - -  /* -   * joins (*,G) -   */ -  if (starch) -    { -      if (PIM_IF_FLAG_TEST_S_G_RPT (starch->upstream->flags)) -        return 0; - -      if (!pim_macro_ch_lost_assert (starch) && pim_macro_chisin_joins_or_include (starch)) -        return 1; -    } - -  return 0; +	if (ch) { +		if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) +			return 0; + +		if (!pim_macro_ch_lost_assert(ch) +		    && pim_macro_chisin_joins_or_include(ch)) +			return 1; +	} + +	/* +	 * joins (*,G) +	 */ +	if (starch) { +		if (PIM_IF_FLAG_TEST_S_G_RPT(starch->upstream->flags)) +			return 0; + +		if (!pim_macro_ch_lost_assert(starch) +		    && pim_macro_chisin_joins_or_include(starch)) +			return 1; +	} + +	return 0;  }  /* @@ -859,7 +834,7 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,    pim_ifp->pim_dr_addr    ch->ifassert_winner_metric    ch->ifassert_winner -  ch->local_ifmembership  +  ch->local_ifmembership    ch->ifjoin_state    ch->upstream->rpf.source_nexthop.mrib_metric_preference    ch->upstream->rpf.source_nexthop.mrib_route_metric @@ -869,31 +844,31 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,   */  int pim_upstream_evaluate_join_desired(struct pim_upstream *up)  { -  struct interface     *ifp; -  struct listnode      *node; -  struct pim_ifchannel *ch, *starch; -  struct pim_upstream  *starup = up->parent; -  int                  ret = 0; +	struct interface *ifp; +	struct listnode *node; +	struct pim_ifchannel *ch, *starch; +	struct pim_upstream *starup = up->parent; +	int ret = 0; -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) -    { -      if (!ifp->info) -        continue; +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		if (!ifp->info) +			continue; -      ch = pim_ifchannel_find (ifp, &up->sg); +		ch = pim_ifchannel_find(ifp, &up->sg); -      if (starup) -        starch = pim_ifchannel_find (ifp, &starup->sg); -      else -        starch = NULL; +		if (starup) +			starch = pim_ifchannel_find(ifp, &starup->sg); +		else +			starch = NULL; -      if (!ch && !starch) -        continue; +		if (!ch && !starch) +			continue; -      ret += pim_upstream_evaluate_join_desired_interface (up, ch, starch); -    } /* scan iface channel list */ +		ret += pim_upstream_evaluate_join_desired_interface(up, ch, +								    starch); +	} /* scan iface channel list */ -  return ret; /* false */ +	return ret; /* false */  }  /* @@ -901,28 +876,28 @@ int pim_upstream_evaluate_join_desired(struct pim_upstream *up)  */  void pim_upstream_update_join_desired(struct pim_upstream *up)  { -  int was_join_desired; /* boolean */ -  int is_join_desired; /* boolean */ - -  was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags); - -  is_join_desired = pim_upstream_evaluate_join_desired(up); -  if (is_join_desired) -    PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags); -  else -    PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags); - -  /* switched from false to true */ -  if (is_join_desired && !was_join_desired) { -    pim_upstream_switch(up, PIM_UPSTREAM_JOINED); -    return; -  } -       -  /* switched from true to false */ -  if (!is_join_desired && was_join_desired) { -    pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED); -    return; -  } +	int was_join_desired; /* boolean */ +	int is_join_desired;  /* boolean */ + +	was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags); + +	is_join_desired = pim_upstream_evaluate_join_desired(up); +	if (is_join_desired) +		PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags); +	else +		PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags); + +	/* switched from false to true */ +	if (is_join_desired && !was_join_desired) { +		pim_upstream_switch(up, PIM_UPSTREAM_JOINED); +		return; +	} + +	/* switched from true to false */ +	if (!is_join_desired && was_join_desired) { +		pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED); +		return; +	}  }  /* @@ -936,110 +911,110 @@ void pim_upstream_update_join_desired(struct pim_upstream *up)  */  void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr)  { -  struct listnode     *up_node; -  struct listnode     *up_nextnode; -  struct pim_upstream *up; - -  /* -   * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr -   */ -  for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { - -    if (PIM_DEBUG_TRACE) { -      char neigh_str[INET_ADDRSTRLEN]; -      char rpf_addr_str[PREFIX_STRLEN]; -      pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, sizeof(neigh_str)); -      pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); -      zlog_debug("%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", -		 __PRETTY_FUNCTION__, -		 neigh_str, up->sg_str, -		 up->join_state == PIM_UPSTREAM_JOINED, -		 rpf_addr_str); -    } - -    /* consider only (S,G) upstream in Joined state */ -    if (up->join_state != PIM_UPSTREAM_JOINED) -      continue; - -    /* match RPF'(S,G)=neigh_addr */ -    if (up->rpf.rpf_addr.u.prefix4.s_addr != neigh_addr.s_addr) -      continue; - -    pim_upstream_join_timer_decrease_to_t_override("RPF'(S,G) GenID change", -                                                   up); -  } +	struct listnode *up_node; +	struct listnode *up_nextnode; +	struct pim_upstream *up; + +	/* +	 * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr +	 */ +	for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { + +		if (PIM_DEBUG_TRACE) { +			char neigh_str[INET_ADDRSTRLEN]; +			char rpf_addr_str[PREFIX_STRLEN]; +			pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, +				       sizeof(neigh_str)); +			pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_addr_str, +				      sizeof(rpf_addr_str)); +			zlog_debug( +				"%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", +				__PRETTY_FUNCTION__, neigh_str, up->sg_str, +				up->join_state == PIM_UPSTREAM_JOINED, +				rpf_addr_str); +		} + +		/* consider only (S,G) upstream in Joined state */ +		if (up->join_state != PIM_UPSTREAM_JOINED) +			continue; + +		/* match RPF'(S,G)=neigh_addr */ +		if (up->rpf.rpf_addr.u.prefix4.s_addr != neigh_addr.s_addr) +			continue; + +		pim_upstream_join_timer_decrease_to_t_override( +			"RPF'(S,G) GenID change", up); +	}  }  void pim_upstream_rpf_interface_changed(struct pim_upstream *up,  					struct interface *old_rpf_ifp)  { -  struct listnode      *chnode; -  struct listnode      *chnextnode; -  struct pim_ifchannel *ch; - -  /* search all ifchannels */ -  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { -    if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { -      if ( -	  /* RPF_interface(S) was NOT I */ -	  (old_rpf_ifp == ch->interface) -	  && -	  /* RPF_interface(S) stopped being I */ -	  (ch->upstream->rpf.source_nexthop.interface != ch->interface) -	  ) { -	assert_action_a5(ch); -      } -    } /* PIM_IFASSERT_I_AM_LOSER */ - -    pim_ifchannel_update_assert_tracking_desired(ch); -  } +	struct listnode *chnode; +	struct listnode *chnextnode; +	struct pim_ifchannel *ch; + +	/* search all ifchannels */ +	for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { +		if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { +			if ( +				/* RPF_interface(S) was NOT I */ +				(old_rpf_ifp == ch->interface) && +				/* RPF_interface(S) stopped being I */ +				(ch->upstream->rpf.source_nexthop +					 .interface != ch->interface)) { +				assert_action_a5(ch); +			} +		} /* PIM_IFASSERT_I_AM_LOSER */ + +		pim_ifchannel_update_assert_tracking_desired(ch); +	}  }  void pim_upstream_update_could_assert(struct pim_upstream *up)  { -  struct listnode      *chnode; -  struct listnode      *chnextnode; -  struct pim_ifchannel *ch; - -  /* scan per-interface (S,G) state */ -  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { -    pim_ifchannel_update_could_assert(ch); -  } /* scan iface channel list */ +	struct listnode *chnode; +	struct listnode *chnextnode; +	struct pim_ifchannel *ch; + +	/* scan per-interface (S,G) state */ +	for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { +		pim_ifchannel_update_could_assert(ch); +	} /* scan iface channel list */  }  void pim_upstream_update_my_assert_metric(struct pim_upstream *up)  { -  struct listnode      *chnode; -  struct listnode      *chnextnode; -  struct pim_ifchannel *ch; +	struct listnode *chnode; +	struct listnode *chnextnode; +	struct pim_ifchannel *ch; -  /* scan per-interface (S,G) state */ -  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { -    pim_ifchannel_update_my_assert_metric(ch); +	/* scan per-interface (S,G) state */ +	for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { +		pim_ifchannel_update_my_assert_metric(ch); -  } /* scan iface channel list */ +	} /* scan iface channel list */  }  static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)  { -  struct listnode      *chnode; -  struct listnode      *chnextnode; -  struct pim_interface *pim_ifp; -  struct pim_ifchannel *ch; - -  /* scan per-interface (S,G) state */ -  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) -    { -      if (!ch->interface) -        continue; -      pim_ifp = ch->interface->info; -      if (!pim_ifp) -        continue; - -      pim_ifchannel_update_assert_tracking_desired(ch); - -    } /* scan iface channel list */ +	struct listnode *chnode; +	struct listnode *chnextnode; +	struct pim_interface *pim_ifp; +	struct pim_ifchannel *ch; + +	/* scan per-interface (S,G) state */ +	for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { +		if (!ch->interface) +			continue; +		pim_ifp = ch->interface->info; +		if (!pim_ifp) +			continue; + +		pim_ifchannel_update_assert_tracking_desired(ch); + +	} /* scan iface channel list */  }  /* When kat is stopped CouldRegister goes to false so we need to @@ -1047,19 +1022,21 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)   * from the OIL */  static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up)  { -  if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) -    return; - -  if (PIM_DEBUG_TRACE) -    zlog_debug ("kat expired on %s; clear fhr reg state", up->sg_str); - -  /* stop reg-stop timer */ -  THREAD_OFF(up->t_rs_timer); -  /* remove regiface from the OIL if it is there*/ -  pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); -  /* clear the register state */ -  up->reg_state = PIM_REG_NOINFO; -  PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags); +	if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) +		return; + +	if (PIM_DEBUG_TRACE) +		zlog_debug("kat expired on %s; clear fhr reg state", +			   up->sg_str); + +	/* stop reg-stop timer */ +	THREAD_OFF(up->t_rs_timer); +	/* remove regiface from the OIL if it is there*/ +	pim_channel_del_oif(up->channel_oil, pim_regiface, +			    PIM_OIF_FLAG_PROTO_PIM); +	/* clear the register state */ +	up->reg_state = PIM_REG_NOINFO; +	PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags);  }  /* When kat is started CouldRegister can go to true. And if it does we @@ -1067,14 +1044,16 @@ static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up)   * to the OIL */  static void pim_upstream_fhr_kat_start(struct pim_upstream *up)  { -  if (pim_upstream_could_register(up)) { -    if (PIM_DEBUG_TRACE) -      zlog_debug ("kat started on %s; set fhr reg state to joined", up->sg_str); - -    PIM_UPSTREAM_FLAG_SET_FHR(up->flags); -    if (up->reg_state == PIM_REG_NOINFO) -      pim_register_join (up); -  } +	if (pim_upstream_could_register(up)) { +		if (PIM_DEBUG_TRACE) +			zlog_debug( +				"kat started on %s; set fhr reg state to joined", +				up->sg_str); + +		PIM_UPSTREAM_FLAG_SET_FHR(up->flags); +		if (up->reg_state == PIM_REG_NOINFO) +			pim_register_join(up); +	}  }  /* @@ -1083,80 +1062,73 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up)   * KAT expiry indicates that flow is inactive. If the flow was created or   * maintained by activity now is the time to deref it.   */ -static int -pim_upstream_keep_alive_timer (struct thread *t) +static int pim_upstream_keep_alive_timer(struct thread *t)  { -  struct pim_upstream *up; - -  up = THREAD_ARG(t); - -  if (I_am_RP (up->sg.grp)) -    { -      pim_br_clear_pmbr (&up->sg); -      /* -       * We need to do more here :) -       * But this is the start. -       */ -    } - -  /* source is no longer active - pull the SA from MSDP's cache */ -  pim_msdp_sa_local_del(&up->sg); - -  /* if entry was created because of activity we need to deref it */ -  if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) -    { -      pim_upstream_fhr_kat_expiry(up); -      if (PIM_DEBUG_TRACE) -	zlog_debug ("kat expired on %s; remove stream reference", up->sg_str); -      PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); -      pim_upstream_del(up, __PRETTY_FUNCTION__); -    } -  else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) -    { -      PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); -      pim_upstream_del(up, __PRETTY_FUNCTION__); -    } - -  return 0; +	struct pim_upstream *up; + +	up = THREAD_ARG(t); + +	if (I_am_RP(up->sg.grp)) { +		pim_br_clear_pmbr(&up->sg); +		/* +		 * We need to do more here :) +		 * But this is the start. +		 */ +	} + +	/* source is no longer active - pull the SA from MSDP's cache */ +	pim_msdp_sa_local_del(&up->sg); + +	/* if entry was created because of activity we need to deref it */ +	if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { +		pim_upstream_fhr_kat_expiry(up); +		if (PIM_DEBUG_TRACE) +			zlog_debug("kat expired on %s; remove stream reference", +				   up->sg_str); +		PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); +		pim_upstream_del(up, __PRETTY_FUNCTION__); +	} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) { +		PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); +		pim_upstream_del(up, __PRETTY_FUNCTION__); +	} + +	return 0;  } -void -pim_upstream_keep_alive_timer_start (struct pim_upstream *up, -				     uint32_t time) +void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time)  { -  if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { -    if (PIM_DEBUG_TRACE) -      zlog_debug ("kat start on %s with no stream reference", up->sg_str); -  } -  THREAD_OFF (up->t_ka_timer); -  thread_add_timer(master, pim_upstream_keep_alive_timer, up, time, -                   &up->t_ka_timer); - -  /* any time keepalive is started against a SG we will have to -   * re-evaluate our active source database */ -  pim_msdp_sa_local_update(up); +	if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { +		if (PIM_DEBUG_TRACE) +			zlog_debug("kat start on %s with no stream reference", +				   up->sg_str); +	} +	THREAD_OFF(up->t_ka_timer); +	thread_add_timer(master, pim_upstream_keep_alive_timer, up, time, +			 &up->t_ka_timer); + +	/* any time keepalive is started against a SG we will have to +	 * re-evaluate our active source database */ +	pim_msdp_sa_local_update(up);  }  /* MSDP on RP needs to know if a source is registerable to this RP */ -static int -pim_upstream_msdp_reg_timer(struct thread *t) +static int pim_upstream_msdp_reg_timer(struct thread *t)  { -  struct pim_upstream *up; +	struct pim_upstream *up; -  up = THREAD_ARG(t); +	up = THREAD_ARG(t); -  /* source is no longer active - pull the SA from MSDP's cache */ -  pim_msdp_sa_local_del(&up->sg); -  return 1; +	/* source is no longer active - pull the SA from MSDP's cache */ +	pim_msdp_sa_local_del(&up->sg); +	return 1;  } -void -pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) +void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)  { -  THREAD_OFF(up->t_msdp_reg_timer); -  thread_add_timer(master, pim_upstream_msdp_reg_timer, up, -                   PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer); +	THREAD_OFF(up->t_msdp_reg_timer); +	thread_add_timer(master, pim_upstream_msdp_reg_timer, up, +			 PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer); -  pim_msdp_sa_local_update(up); +	pim_msdp_sa_local_update(up);  }  /* @@ -1187,28 +1159,25 @@ pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)   *  SwitchToSptDesired(S,G) return true once a single packet has been   *  received for the source and group.   */ -int -pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) +int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg)  { -  if (I_am_RP (sg->grp)) -    return 1; +	if (I_am_RP(sg->grp)) +		return 1; -  return 0; +	return 0;  } -int -pim_upstream_is_sg_rpt (struct pim_upstream *up) +int pim_upstream_is_sg_rpt(struct pim_upstream *up)  { -  struct listnode *chnode; -  struct pim_ifchannel *ch; +	struct listnode *chnode; +	struct pim_ifchannel *ch; -  for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch)) -    { -      if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) -        return 1; -    } +	for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch)) { +		if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) +			return 1; +	} -  return 0; +	return 0;  }  /*   *  After receiving a packet set SPTbit: @@ -1226,241 +1195,238 @@ pim_upstream_is_sg_rpt (struct pim_upstream *up)   *     }   *   }   */ -void -pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) +void pim_upstream_set_sptbit(struct pim_upstream *up, +			     struct interface *incoming)  { -  struct pim_upstream *starup = up->parent; - -  // iif == RPF_interfvace(S) -  if (up->rpf.source_nexthop.interface != incoming) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug ("%s: Incoming Interface: %s is different than RPF_interface(S) %s", -		    __PRETTY_FUNCTION__, incoming->name, up->rpf.source_nexthop.interface->name); -      return; -    } - -  // AND JoinDesired(S,G) == TRUE -  // FIXME - -  // DirectlyConnected(S) == TRUE -  if (pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug ("%s: %s is directly connected to the source", __PRETTY_FUNCTION__, -		    up->sg_str); -      up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; -      return; -     } - -  // OR RPF_interface(S) != RPF_interface(RP(G)) -  if (!starup || up->rpf.source_nexthop.interface != starup->rpf.source_nexthop.interface) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug ("%s: %s RPF_interface(S) != RPF_interface(RP(G))", -		    __PRETTY_FUNCTION__, up->sg_str); -      up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; -      return; -    } - -  // OR inherited_olist(S,G,rpt) == NULL -  if (pim_upstream_is_sg_rpt(up) && pim_upstream_empty_inherited_olist(up)) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug ("%s: %s OR inherited_olist(S,G,rpt) == NULL", __PRETTY_FUNCTION__, -		    up->sg_str); -      up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; -      return; -    } - -  // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND -  //      ( RPF'(S,G) != NULL ) ) -  if (up->parent && pim_rpf_is_same (&up->rpf, &up->parent->rpf)) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug ("%s: %s RPF'(S,G) is the same as RPF'(*,G)", __PRETTY_FUNCTION__, -		    up->sg_str); -      up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; -      return; -    } - -  return; +	struct pim_upstream *starup = up->parent; + +	// iif == RPF_interfvace(S) +	if (up->rpf.source_nexthop.interface != incoming) { +		if (PIM_DEBUG_TRACE) +			zlog_debug( +				"%s: Incoming Interface: %s is different than RPF_interface(S) %s", +				__PRETTY_FUNCTION__, incoming->name, +				up->rpf.source_nexthop.interface->name); +		return; +	} + +	// AND JoinDesired(S,G) == TRUE +	// FIXME + +	// DirectlyConnected(S) == TRUE +	if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, +				       up->sg.src)) { +		if (PIM_DEBUG_TRACE) +			zlog_debug("%s: %s is directly connected to the source", +				   __PRETTY_FUNCTION__, up->sg_str); +		up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; +		return; +	} + +	// OR RPF_interface(S) != RPF_interface(RP(G)) +	if (!starup +	    || up->rpf.source_nexthop +			       .interface != starup->rpf.source_nexthop.interface) { +		if (PIM_DEBUG_TRACE) +			zlog_debug( +				"%s: %s RPF_interface(S) != RPF_interface(RP(G))", +				__PRETTY_FUNCTION__, up->sg_str); +		up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; +		return; +	} + +	// OR inherited_olist(S,G,rpt) == NULL +	if (pim_upstream_is_sg_rpt(up) +	    && pim_upstream_empty_inherited_olist(up)) { +		if (PIM_DEBUG_TRACE) +			zlog_debug("%s: %s OR inherited_olist(S,G,rpt) == NULL", +				   __PRETTY_FUNCTION__, up->sg_str); +		up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; +		return; +	} + +	// OR ( ( RPF'(S,G) == RPF'(*,G) ) AND +	//      ( RPF'(S,G) != NULL ) ) +	if (up->parent && pim_rpf_is_same(&up->rpf, &up->parent->rpf)) { +		if (PIM_DEBUG_TRACE) +			zlog_debug("%s: %s RPF'(S,G) is the same as RPF'(*,G)", +				   __PRETTY_FUNCTION__, up->sg_str); +		up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; +		return; +	} + +	return;  } -const char * -pim_upstream_state2str (enum pim_upstream_state join_state) +const char *pim_upstream_state2str(enum pim_upstream_state join_state)  { -  switch (join_state) -    { -    case PIM_UPSTREAM_NOTJOINED: -      return "NotJoined"; -      break; -    case PIM_UPSTREAM_JOINED: -      return "Joined"; -      break; -    } -  return "Unknown"; +	switch (join_state) { +	case PIM_UPSTREAM_NOTJOINED: +		return "NotJoined"; +		break; +	case PIM_UPSTREAM_JOINED: +		return "Joined"; +		break; +	} +	return "Unknown";  } -const char * -pim_reg_state2str (enum pim_reg_state reg_state, char *state_str) +const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str)  { -  switch (reg_state) -    { -    case PIM_REG_NOINFO: -      strcpy (state_str, "RegNoInfo"); -      break; -    case PIM_REG_JOIN: -      strcpy (state_str, "RegJoined"); -      break; -    case PIM_REG_JOIN_PENDING: -      strcpy (state_str, "RegJoinPend"); -      break; -    case PIM_REG_PRUNE: -      strcpy (state_str, "RegPrune"); -      break; -    default: -      strcpy (state_str, "RegUnknown"); -    } -  return state_str; +	switch (reg_state) { +	case PIM_REG_NOINFO: +		strcpy(state_str, "RegNoInfo"); +		break; +	case PIM_REG_JOIN: +		strcpy(state_str, "RegJoined"); +		break; +	case PIM_REG_JOIN_PENDING: +		strcpy(state_str, "RegJoinPend"); +		break; +	case PIM_REG_PRUNE: +		strcpy(state_str, "RegPrune"); +		break; +	default: +		strcpy(state_str, "RegUnknown"); +	} +	return state_str;  } -static int -pim_upstream_register_stop_timer (struct thread *t) +static int pim_upstream_register_stop_timer(struct thread *t)  { -  struct pim_interface *pim_ifp; -  struct pim_upstream *up; -  struct pim_rpf *rpg; -  struct ip ip_hdr; -  up = THREAD_ARG (t); - -  if (PIM_DEBUG_TRACE) -    { -      char state_str[PIM_REG_STATE_STR_LEN]; -      zlog_debug ("%s: (S,G)=%s upstream register stop timer %s", -		  __PRETTY_FUNCTION__, up->sg_str, -                  pim_reg_state2str(up->reg_state, state_str)); -    } - -  switch (up->reg_state) -    { -    case PIM_REG_JOIN_PENDING: -      up->reg_state = PIM_REG_JOIN; -      pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); -      break; -    case PIM_REG_JOIN: -      break; -    case PIM_REG_PRUNE: -      pim_ifp = up->rpf.source_nexthop.interface->info; -      if (!pim_ifp) -        { -         if (PIM_DEBUG_TRACE) -           zlog_debug ("%s: Interface: %s is not configured for pim", -                       __PRETTY_FUNCTION__, up->rpf.source_nexthop.interface->name); -         return 0; -       } -      up->reg_state = PIM_REG_JOIN_PENDING; -      pim_upstream_start_register_stop_timer (up, 1); - -      if (((up->channel_oil->cc.lastused/100) > PIM_KEEPALIVE_PERIOD) && -	  (I_am_RP (up->sg.grp))) -	{ -	  if (PIM_DEBUG_TRACE) -	    zlog_debug ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while", __PRETTY_FUNCTION__); -	  return 0; +	struct pim_interface *pim_ifp; +	struct pim_upstream *up; +	struct pim_rpf *rpg; +	struct ip ip_hdr; +	up = THREAD_ARG(t); + +	if (PIM_DEBUG_TRACE) { +		char state_str[PIM_REG_STATE_STR_LEN]; +		zlog_debug("%s: (S,G)=%s upstream register stop timer %s", +			   __PRETTY_FUNCTION__, up->sg_str, +			   pim_reg_state2str(up->reg_state, state_str)); +	} + +	switch (up->reg_state) { +	case PIM_REG_JOIN_PENDING: +		up->reg_state = PIM_REG_JOIN; +		pim_channel_add_oif(up->channel_oil, pim_regiface, +				    PIM_OIF_FLAG_PROTO_PIM); +		break; +	case PIM_REG_JOIN: +		break; +	case PIM_REG_PRUNE: +		pim_ifp = up->rpf.source_nexthop.interface->info; +		if (!pim_ifp) { +			if (PIM_DEBUG_TRACE) +				zlog_debug( +					"%s: Interface: %s is not configured for pim", +					__PRETTY_FUNCTION__, +					up->rpf.source_nexthop.interface->name); +			return 0; +		} +		up->reg_state = PIM_REG_JOIN_PENDING; +		pim_upstream_start_register_stop_timer(up, 1); + +		if (((up->channel_oil->cc.lastused / 100) +		     > PIM_KEEPALIVE_PERIOD) +		    && (I_am_RP(up->sg.grp))) { +			if (PIM_DEBUG_TRACE) +				zlog_debug( +					"%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while", +					__PRETTY_FUNCTION__); +			return 0; +		} +		rpg = RP(up->sg.grp); +		memset(&ip_hdr, 0, sizeof(struct ip)); +		ip_hdr.ip_p = PIM_IP_PROTO_PIM; +		ip_hdr.ip_hl = 5; +		ip_hdr.ip_v = 4; +		ip_hdr.ip_src = up->sg.src; +		ip_hdr.ip_dst = up->sg.grp; +		ip_hdr.ip_len = htons(20); +		// checksum is broken +		pim_register_send((uint8_t *)&ip_hdr, sizeof(struct ip), +				  pim_ifp->primary_address, rpg, 1, up); +		break; +	default: +		break;  	} -      rpg = RP (up->sg.grp); -      memset (&ip_hdr, 0, sizeof (struct ip)); -      ip_hdr.ip_p = PIM_IP_PROTO_PIM; -      ip_hdr.ip_hl = 5; -      ip_hdr.ip_v = 4; -      ip_hdr.ip_src = up->sg.src; -      ip_hdr.ip_dst = up->sg.grp; -      ip_hdr.ip_len = htons (20); -      // checksum is broken -      pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), -			 pim_ifp->primary_address, rpg, 1, up); -      break; -    default: -      break; -    } - -  return 0; + +	return 0;  } -void -pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register) +void pim_upstream_start_register_stop_timer(struct pim_upstream *up, +					    int null_register)  { -  uint32_t time; - -  THREAD_TIMER_OFF (up->t_rs_timer); - -  if (!null_register) -    { -      uint32_t lower = (0.5 * PIM_REGISTER_SUPPRESSION_PERIOD); -      uint32_t upper = (1.5 * PIM_REGISTER_SUPPRESSION_PERIOD); -      time = lower + (random () % (upper - lower + 1)) - PIM_REGISTER_PROBE_PERIOD; -    } -  else -    time = PIM_REGISTER_PROBE_PERIOD; - -  if (PIM_DEBUG_TRACE) -    { -      zlog_debug ("%s: (S,G)=%s Starting upstream register stop timer %d", -		  __PRETTY_FUNCTION__, up->sg_str, time); -    } -  thread_add_timer(master, pim_upstream_register_stop_timer, up, time, -                   &up->t_rs_timer); +	uint32_t time; + +	THREAD_TIMER_OFF(up->t_rs_timer); + +	if (!null_register) { +		uint32_t lower = (0.5 * PIM_REGISTER_SUPPRESSION_PERIOD); +		uint32_t upper = (1.5 * PIM_REGISTER_SUPPRESSION_PERIOD); +		time = lower + (random() % (upper - lower + 1)) +		       - PIM_REGISTER_PROBE_PERIOD; +	} else +		time = PIM_REGISTER_PROBE_PERIOD; + +	if (PIM_DEBUG_TRACE) { +		zlog_debug( +			"%s: (S,G)=%s Starting upstream register stop timer %d", +			__PRETTY_FUNCTION__, up->sg_str, time); +	} +	thread_add_timer(master, pim_upstream_register_stop_timer, up, time, +			 &up->t_rs_timer);  } -int -pim_upstream_inherited_olist_decide (struct pim_upstream *up) +int pim_upstream_inherited_olist_decide(struct pim_upstream *up)  { -  struct interface *ifp; -  struct pim_interface *pim_ifp = NULL; -  struct pim_ifchannel *ch, *starch; -  struct listnode *node; -  struct pim_upstream *starup = up->parent; -  int output_intf = 0; - -  if (up->rpf.source_nexthop.interface) -    pim_ifp = up->rpf.source_nexthop.interface->info; -  else -    { -      if (PIM_DEBUG_TRACE) -        zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str); -    } -  if (pim_ifp && !up->channel_oil) -    up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) -    { -      if (!ifp->info) -        continue; - -      ch = pim_ifchannel_find (ifp, &up->sg); - -      if (starup) -        starch = pim_ifchannel_find (ifp, &starup->sg); -      else -        starch = NULL; - -      if (!ch && !starch) -        continue; - -      if (pim_upstream_evaluate_join_desired_interface (up, ch, starch)) -        { -          int flag = PIM_OIF_FLAG_PROTO_PIM; - -          if (!ch) -            flag = PIM_OIF_FLAG_PROTO_STAR; - -          pim_channel_add_oif (up->channel_oil, ifp, flag); -          output_intf++; -        } -    } - -  return output_intf; +	struct interface *ifp; +	struct pim_interface *pim_ifp = NULL; +	struct pim_ifchannel *ch, *starch; +	struct listnode *node; +	struct pim_upstream *starup = up->parent; +	int output_intf = 0; + +	if (up->rpf.source_nexthop.interface) +		pim_ifp = up->rpf.source_nexthop.interface->info; +	else { +		if (PIM_DEBUG_TRACE) +			zlog_debug("%s: up %s RPF is not present", +				   __PRETTY_FUNCTION__, up->sg_str); +	} +	if (pim_ifp && !up->channel_oil) +		up->channel_oil = +			pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index); + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		if (!ifp->info) +			continue; + +		ch = pim_ifchannel_find(ifp, &up->sg); + +		if (starup) +			starch = pim_ifchannel_find(ifp, &starup->sg); +		else +			starch = NULL; + +		if (!ch && !starch) +			continue; + +		if (pim_upstream_evaluate_join_desired_interface(up, ch, +								 starch)) { +			int flag = PIM_OIF_FLAG_PROTO_PIM; + +			if (!ch) +				flag = PIM_OIF_FLAG_PROTO_STAR; + +			pim_channel_add_oif(up->channel_oil, ifp, flag); +			output_intf++; +		} +	} + +	return output_intf;  }  /* @@ -1479,29 +1445,27 @@ pim_upstream_inherited_olist_decide (struct pim_upstream *up)   * return 1 if there are any output interfaces   * return 0 if there are not any output interfaces   */ -int -pim_upstream_inherited_olist (struct pim_upstream *up) +int pim_upstream_inherited_olist(struct pim_upstream *up)  { -  int output_intf =  pim_upstream_inherited_olist_decide (up); - -  /* -   * If we have output_intf switch state to Join and work like normal -   * If we don't have an output_intf that means we are probably a -   * switch on a stick so turn on forwarding to just accept the -   * incoming packets so we don't bother the other stuff! -   */ -  if (output_intf) -    pim_upstream_switch (up, PIM_UPSTREAM_JOINED); -  else -    forward_on (up); - -  return output_intf; +	int output_intf = pim_upstream_inherited_olist_decide(up); + +	/* +	 * If we have output_intf switch state to Join and work like normal +	 * If we don't have an output_intf that means we are probably a +	 * switch on a stick so turn on forwarding to just accept the +	 * incoming packets so we don't bother the other stuff! +	 */ +	if (output_intf) +		pim_upstream_switch(up, PIM_UPSTREAM_JOINED); +	else +		forward_on(up); + +	return output_intf;  } -int -pim_upstream_empty_inherited_olist (struct pim_upstream *up) +int pim_upstream_empty_inherited_olist(struct pim_upstream *up)  { -  return pim_channel_oil_empty (up->channel_oil); +	return pim_channel_oil_empty(up->channel_oil);  }  /* @@ -1510,58 +1474,54 @@ pim_upstream_empty_inherited_olist (struct pim_upstream *up)   * set and see if the new neighbor allows   * the join to be sent   */ -void -pim_upstream_find_new_rpf (void) +void pim_upstream_find_new_rpf(void)  { -  struct listnode     *up_node; -  struct listnode     *up_nextnode; -  struct pim_upstream *up; - -  /* -   * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr -   */ -  for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) -    { -      if (pim_rpf_addr_is_inaddr_any(&up->rpf)) -	{ -	  if (PIM_DEBUG_TRACE) -	    zlog_debug ("Upstream %s without a path to send join, checking", -			up->sg_str); -	  pim_rpf_update (up, NULL, 1); +	struct listnode *up_node; +	struct listnode *up_nextnode; +	struct pim_upstream *up; + +	/* +	 * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr +	 */ +	for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { +		if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { +			if (PIM_DEBUG_TRACE) +				zlog_debug( +					"Upstream %s without a path to send join, checking", +					up->sg_str); +			pim_rpf_update(up, NULL, 1); +		}  	} -    }  } -static unsigned int -pim_upstream_hash_key (void *arg) +static unsigned int pim_upstream_hash_key(void *arg)  { -  struct pim_upstream *up = (struct pim_upstream *)arg; +	struct pim_upstream *up = (struct pim_upstream *)arg; -  return jhash_2words (up->sg.src.s_addr, up->sg.grp.s_addr, 0); +	return jhash_2words(up->sg.src.s_addr, up->sg.grp.s_addr, 0);  } -void pim_upstream_terminate (void) +void pim_upstream_terminate(void)  { -  if (pim_upstream_list) -    list_delete (pim_upstream_list); -  pim_upstream_list = NULL; +	if (pim_upstream_list) +		list_delete(pim_upstream_list); +	pim_upstream_list = NULL; -  if (pim_upstream_hash) -    hash_free (pim_upstream_hash); -  pim_upstream_hash = NULL; +	if (pim_upstream_hash) +		hash_free(pim_upstream_hash); +	pim_upstream_hash = NULL;  } -static int -pim_upstream_equal (const void *arg1, const void *arg2) +static int pim_upstream_equal(const void *arg1, const void *arg2)  { -  const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; -  const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; +	const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; +	const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; -  if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) && -      (up1->sg.src.s_addr == up2->sg.src.s_addr)) -    return 1; +	if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) +	    && (up1->sg.src.s_addr == up2->sg.src.s_addr)) +		return 1; -  return 0; +	return 0;  }  /* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines @@ -1580,129 +1540,128 @@ pim_upstream_equal (const void *arg1, const void *arg2)   */  static bool pim_upstream_kat_start_ok(struct pim_upstream *up)  { -  /* "iif == RPF_interface(S)" check has to be done by the kernel or hw -   * so we will skip that here */ -  if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, -        up->sg.src)) { -    return true; -  } - -  if ((up->join_state == PIM_UPSTREAM_JOINED) && -            !pim_upstream_empty_inherited_olist(up)) { -    /* XXX: I have added this RP check just for 3.2 and it's a digression from -     * what rfc-4601 says. Till now we were only running KAT on FHR and RP and -     * there is some angst around making the change to run it all routers that -     * maintain the (S, G) state. This is tracked via CM-13601 and MUST be -     * removed to handle spt turn-arounds correctly in a 3-tier clos */ -    if (I_am_RP (up->sg.grp)) -      return true; -  } - -  return false; +	/* "iif == RPF_interface(S)" check has to be done by the kernel or hw +	 * so we will skip that here */ +	if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, +				       up->sg.src)) { +		return true; +	} + +	if ((up->join_state == PIM_UPSTREAM_JOINED) +	    && !pim_upstream_empty_inherited_olist(up)) { +		/* XXX: I have added this RP check just for 3.2 and it's a +		 * digression from +		 * what rfc-4601 says. Till now we were only running KAT on FHR +		 * and RP and +		 * there is some angst around making the change to run it all +		 * routers that +		 * maintain the (S, G) state. This is tracked via CM-13601 and +		 * MUST be +		 * removed to handle spt turn-arounds correctly in a 3-tier clos +		 */ +		if (I_am_RP(up->sg.grp)) +			return true; +	} + +	return false;  }  /*   * Code to check and see if we've received packets on a S,G mroute   * and if so to set the SPT bit appropriately   */ -static void -pim_upstream_sg_running (void *arg) +static void pim_upstream_sg_running(void *arg)  { -  struct pim_upstream *up = (struct pim_upstream *)arg; - -  // No packet can have arrived here if this is the case -  if (!up->channel_oil || !up->channel_oil->installed) -    { -      if (PIM_DEBUG_TRACE) -	zlog_debug ("%s: %s is not installed in mroute", -		    __PRETTY_FUNCTION__, up->sg_str); -      return; -    } - -  /* -   * This is a bit of a hack -   * We've noted that we should rescan but -   * we've missed the window for doing so in -   * pim_zebra.c for some reason.  I am -   * only doing this at this point in time -   * to get us up and working for the moment -   */ -  if (up->channel_oil->oil_inherited_rescan) -    { -      if (PIM_DEBUG_TRACE) -        zlog_debug ("%s: Handling unscanned inherited_olist for %s", __PRETTY_FUNCTION__, up->sg_str); -      pim_upstream_inherited_olist_decide (up); -      up->channel_oil->oil_inherited_rescan = 0; -    } -  pim_mroute_update_counters (up->channel_oil); - -  // Have we seen packets? -  if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && -      (up->channel_oil->cc.lastused/100 > 30)) -    { -      if (PIM_DEBUG_TRACE) -	{ -	  zlog_debug ("%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)", -		      __PRETTY_FUNCTION__, up->sg_str, -		      up->channel_oil->cc.oldpktcnt, -		      up->channel_oil->cc.pktcnt, -		      up->channel_oil->cc.lastused/100); +	struct pim_upstream *up = (struct pim_upstream *)arg; + +	// No packet can have arrived here if this is the case +	if (!up->channel_oil || !up->channel_oil->installed) { +		if (PIM_DEBUG_TRACE) +			zlog_debug("%s: %s is not installed in mroute", +				   __PRETTY_FUNCTION__, up->sg_str); +		return; +	} + +	/* +	 * This is a bit of a hack +	 * We've noted that we should rescan but +	 * we've missed the window for doing so in +	 * pim_zebra.c for some reason.  I am +	 * only doing this at this point in time +	 * to get us up and working for the moment +	 */ +	if (up->channel_oil->oil_inherited_rescan) { +		if (PIM_DEBUG_TRACE) +			zlog_debug( +				"%s: Handling unscanned inherited_olist for %s", +				__PRETTY_FUNCTION__, up->sg_str); +		pim_upstream_inherited_olist_decide(up); +		up->channel_oil->oil_inherited_rescan = 0; +	} +	pim_mroute_update_counters(up->channel_oil); + +	// Have we seen packets? +	if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) +	    && (up->channel_oil->cc.lastused / 100 > 30)) { +		if (PIM_DEBUG_TRACE) { +			zlog_debug( +				"%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)", +				__PRETTY_FUNCTION__, up->sg_str, +				up->channel_oil->cc.oldpktcnt, +				up->channel_oil->cc.pktcnt, +				up->channel_oil->cc.lastused / 100); +		} +		return;  	} -      return; -    } - -  if (pim_upstream_kat_start_ok(up)) -    { -      /* Add a source reference to the stream if -       * one doesn't already exist */ -      if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) -	{ -	  if (PIM_DEBUG_TRACE) -	    zlog_debug ("source reference created on kat restart %s", up->sg_str); - -	  pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __PRETTY_FUNCTION__); -	  PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); -	  pim_upstream_fhr_kat_start(up); + +	if (pim_upstream_kat_start_ok(up)) { +		/* Add a source reference to the stream if +		 * one doesn't already exist */ +		if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { +			if (PIM_DEBUG_TRACE) +				zlog_debug( +					"source reference created on kat restart %s", +					up->sg_str); + +			pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, +					 __PRETTY_FUNCTION__); +			PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); +			pim_upstream_fhr_kat_start(up); +		} +		pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); +	} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) +		pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + +	if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) { +		pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);  	} -      pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); -    } -  else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) -    pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); - -  if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) -    { -      pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); -    } -  return; +	return;  } -void -pim_upstream_add_lhr_star_pimreg (void) +void pim_upstream_add_lhr_star_pimreg(void)  { -  struct pim_upstream *up; -  struct listnode *node; +	struct pim_upstream *up; +	struct listnode *node; -  for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) -    { -      if (up->sg.src.s_addr != INADDR_ANY) -        continue; +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) { +		if (up->sg.src.s_addr != INADDR_ANY) +			continue; -      if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) -        continue; +		if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) +			continue; -      pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); -    } +		pim_channel_add_oif(up->channel_oil, pim_regiface, +				    PIM_OIF_FLAG_PROTO_IGMP); +	}  } -void -pim_upstream_spt_prefix_list_update (struct prefix_list *pl) +void pim_upstream_spt_prefix_list_update(struct prefix_list *pl)  { -  const char *pname = prefix_list_name (pl); +	const char *pname = prefix_list_name(pl); -  if (pimg->spt.plist && strcmp (pimg->spt.plist, pname) == 0) -    { -      pim_upstream_remove_lhr_star_pimreg (pname); -    } +	if (pimg->spt.plist && strcmp(pimg->spt.plist, pname) == 0) { +		pim_upstream_remove_lhr_star_pimreg(pname); +	}  }  /* @@ -1717,53 +1676,51 @@ pim_upstream_spt_prefix_list_update (struct prefix_list *pl)   * the interface   *   */ -void -pim_upstream_remove_lhr_star_pimreg (const char *nlist) +void pim_upstream_remove_lhr_star_pimreg(const char *nlist)  { -  struct pim_upstream *up; -  struct listnode *node; -  struct prefix_list *np; -  struct prefix g; -  enum prefix_list_type apply_new; - -  np = prefix_list_lookup (AFI_IP, nlist); - -  g.family = AF_INET; -  g.prefixlen = IPV4_MAX_PREFIXLEN; - -  for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) -    { -      if (up->sg.src.s_addr != INADDR_ANY) -        continue; - -      if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) -        continue; - -      if (!nlist) -        { -          pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); -          continue; -        } -      g.u.prefix4 = up->sg.grp; -      apply_new = prefix_list_apply (np, &g); -      if (apply_new == PREFIX_DENY) -        pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); -      else -        pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); -    } +	struct pim_upstream *up; +	struct listnode *node; +	struct prefix_list *np; +	struct prefix g; +	enum prefix_list_type apply_new; + +	np = prefix_list_lookup(AFI_IP, nlist); + +	g.family = AF_INET; +	g.prefixlen = IPV4_MAX_PREFIXLEN; + +	for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) { +		if (up->sg.src.s_addr != INADDR_ANY) +			continue; + +		if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) +			continue; + +		if (!nlist) { +			pim_channel_del_oif(up->channel_oil, pim_regiface, +					    PIM_OIF_FLAG_PROTO_IGMP); +			continue; +		} +		g.u.prefix4 = up->sg.grp; +		apply_new = prefix_list_apply(np, &g); +		if (apply_new == PREFIX_DENY) +			pim_channel_add_oif(up->channel_oil, pim_regiface, +					    PIM_OIF_FLAG_PROTO_IGMP); +		else +			pim_channel_del_oif(up->channel_oil, pim_regiface, +					    PIM_OIF_FLAG_PROTO_IGMP); +	}  } -void -pim_upstream_init (void) +void pim_upstream_init(void)  { -  pim_upstream_sg_wheel = wheel_init (master, 31000, 100, -				      pim_upstream_hash_key, -				      pim_upstream_sg_running); -  pim_upstream_hash = hash_create_size (8192, pim_upstream_hash_key, -					pim_upstream_equal, NULL); - -  pim_upstream_list = list_new (); -  pim_upstream_list->del = (void (*)(void *)) pim_upstream_free; -  pim_upstream_list->cmp = pim_upstream_compare; - +	pim_upstream_sg_wheel = +		wheel_init(master, 31000, 100, pim_upstream_hash_key, +			   pim_upstream_sg_running); +	pim_upstream_hash = hash_create_size(8192, pim_upstream_hash_key, +					     pim_upstream_equal, NULL); + +	pim_upstream_list = list_new(); +	pim_upstream_list->del = (void (*)(void *))pim_upstream_free; +	pim_upstream_list->cmp = pim_upstream_compare;  } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index acb4b17c7d..b6a9729f0f 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -70,100 +70,102 @@  #define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR)  enum pim_upstream_state { -  PIM_UPSTREAM_NOTJOINED, -  PIM_UPSTREAM_JOINED, +	PIM_UPSTREAM_NOTJOINED, +	PIM_UPSTREAM_JOINED,  };  enum pim_reg_state { -  PIM_REG_NOINFO, -  PIM_REG_JOIN, -  PIM_REG_JOIN_PENDING, -  PIM_REG_PRUNE, +	PIM_REG_NOINFO, +	PIM_REG_JOIN, +	PIM_REG_JOIN_PENDING, +	PIM_REG_PRUNE,  };  enum pim_upstream_sptbit { -  PIM_UPSTREAM_SPTBIT_FALSE, -  PIM_UPSTREAM_SPTBIT_TRUE +	PIM_UPSTREAM_SPTBIT_FALSE, +	PIM_UPSTREAM_SPTBIT_TRUE  };  /*    Upstream (S,G) channel in Joined state -   +    (S,G) in the "Not Joined" state is not represented -   +    See RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Message  */  struct pim_upstream { -  struct pim_upstream      *parent; -  struct in_addr           upstream_addr;/* Who we are talking to */ -  struct in_addr           upstream_register; /*Who we received a register from*/ -  struct prefix_sg         sg;           /* (S,G) group key */ -  char                     sg_str[PIM_SG_LEN]; -  uint32_t                 flags; -  struct channel_oil      *channel_oil; -  struct list             *sources; -  struct list             *ifchannels; - -  enum pim_upstream_state  join_state; -  enum pim_reg_state       reg_state; -  enum pim_upstream_sptbit sptbit; - -  int                      ref_count; - -  struct pim_rpf           rpf; - -  struct thread           *t_join_timer; - -  /* -   * RST(S,G) -   */ -  struct thread           *t_rs_timer; +	struct pim_upstream *parent; +	struct in_addr upstream_addr;     /* Who we are talking to */ +	struct in_addr upstream_register; /*Who we received a register from*/ +	struct prefix_sg sg;		  /* (S,G) group key */ +	char sg_str[PIM_SG_LEN]; +	uint32_t flags; +	struct channel_oil *channel_oil; +	struct list *sources; +	struct list *ifchannels; + +	enum pim_upstream_state join_state; +	enum pim_reg_state reg_state; +	enum pim_upstream_sptbit sptbit; + +	int ref_count; + +	struct pim_rpf rpf; + +	struct thread *t_join_timer; + +	/* +	 * RST(S,G) +	 */ +	struct thread *t_rs_timer;  #define PIM_REGISTER_SUPPRESSION_PERIOD (60)  #define PIM_REGISTER_PROBE_PERIOD       (15) -  /* -   * KAT(S,G) -   */ -  struct thread           *t_ka_timer; +	/* +	 * KAT(S,G) +	 */ +	struct thread *t_ka_timer;  #define PIM_KEEPALIVE_PERIOD  (210)  #define PIM_RP_KEEPALIVE_PERIOD ( 3 * qpim_register_suppress_time + qpim_register_probe_time ) -  /* on the RP we restart a timer to indicate if registers are being rxed for -   * SG. This is needed by MSDP to determine its local SA cache */ -  struct thread           *t_msdp_reg_timer; +	/* on the RP we restart a timer to indicate if registers are being rxed +	 * for +	 * SG. This is needed by MSDP to determine its local SA cache */ +	struct thread *t_msdp_reg_timer;  #define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * qpim_register_suppress_time)) -  int64_t                  state_transition; /* Record current state uptime */ +	int64_t state_transition; /* Record current state uptime */  };  struct list *pim_upstream_list;  struct hash *pim_upstream_hash;  void pim_upstream_free(struct pim_upstream *up); -struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); -struct pim_upstream *pim_upstream_find_or_add (struct prefix_sg *sg, -                                               struct interface *ifp, int flags, -                                               const char *name); -struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, -				       struct interface *ifp, int flags, -				       const char *name); -void pim_upstream_ref (struct pim_upstream *up, int flags, const char *name); -struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name); +struct pim_upstream *pim_upstream_find(struct prefix_sg *sg); +struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, +					      struct interface *ifp, int flags, +					      const char *name); +struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, +				      struct interface *ifp, int flags, +				      const char *name); +void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name); +struct pim_upstream *pim_upstream_del(struct pim_upstream *up, +				      const char *name);  int pim_upstream_evaluate_join_desired(struct pim_upstream *up);  int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up, -                                                 struct pim_ifchannel *ch, -                                                 struct pim_ifchannel *starch); +						 struct pim_ifchannel *ch, +						 struct pim_ifchannel *starch);  void pim_upstream_update_join_desired(struct pim_upstream *up);  void pim_upstream_join_suppress(struct pim_upstream *up, -				struct in_addr rpf_addr, -				int holdtime); +				struct in_addr rpf_addr, int holdtime);  void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, -                                                    struct pim_upstream *up); +						    struct pim_upstream *up); -void pim_upstream_join_timer_restart(struct pim_upstream *up, struct pim_rpf *old); +void pim_upstream_join_timer_restart(struct pim_upstream *up, +				     struct pim_rpf *old);  void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr);  void pim_upstream_rpf_interface_changed(struct pim_upstream *up,  					struct interface *old_rpf_ifp); @@ -171,40 +173,44 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up,  void pim_upstream_update_could_assert(struct pim_upstream *up);  void pim_upstream_update_my_assert_metric(struct pim_upstream *up); -void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time); +void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, +					 uint32_t time); -int pim_upstream_switch_to_spt_desired (struct prefix_sg *sg); +int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg);  #define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg) -int pim_upstream_is_sg_rpt (struct pim_upstream *up); +int pim_upstream_is_sg_rpt(struct pim_upstream *up); -void pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming); +void pim_upstream_set_sptbit(struct pim_upstream *up, +			     struct interface *incoming); -void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); +void pim_upstream_start_register_stop_timer(struct pim_upstream *up, +					    int null_register); -void pim_upstream_send_join (struct pim_upstream *up); +void pim_upstream_send_join(struct pim_upstream *up); -void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_state); +void pim_upstream_switch(struct pim_upstream *up, +			 enum pim_upstream_state new_state); -const char *pim_upstream_state2str (enum pim_upstream_state join_state); +const char *pim_upstream_state2str(enum pim_upstream_state join_state);  #define PIM_REG_STATE_STR_LEN 12 -const char *pim_reg_state2str (enum pim_reg_state state, char *state_str); +const char *pim_reg_state2str(enum pim_reg_state state, char *state_str); -int pim_upstream_inherited_olist_decide (struct pim_upstream *up); -int pim_upstream_inherited_olist (struct pim_upstream *up); -int pim_upstream_empty_inherited_olist (struct pim_upstream *up); +int pim_upstream_inherited_olist_decide(struct pim_upstream *up); +int pim_upstream_inherited_olist(struct pim_upstream *up); +int pim_upstream_empty_inherited_olist(struct pim_upstream *up); -void pim_upstream_find_new_rpf (void); +void pim_upstream_find_new_rpf(void);  void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up); -void pim_upstream_init (void); -void pim_upstream_terminate (void); +void pim_upstream_init(void); +void pim_upstream_terminate(void); -void join_timer_start (struct pim_upstream *up); -int pim_upstream_compare (void *arg1, void *arg2); -void pim_upstream_register_reevaluate (void); +void join_timer_start(struct pim_upstream *up); +int pim_upstream_compare(void *arg1, void *arg2); +void pim_upstream_register_reevaluate(void); -void pim_upstream_add_lhr_star_pimreg (void); -void pim_upstream_remove_lhr_star_pimreg (const char *nlist); +void pim_upstream_add_lhr_star_pimreg(void); +void pim_upstream_remove_lhr_star_pimreg(const char *nlist); -void pim_upstream_spt_prefix_list_update (struct prefix_list *pl); +void pim_upstream_spt_prefix_list_update(struct prefix_list *pl);  #endif /* PIM_UPSTREAM_H */ diff --git a/pimd/pim_util.c b/pimd/pim_util.c index 139c0e3fb1..c2e4b2a462 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -26,18 +26,18 @@  /*    RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) -   +    If QQIC < 128,  QQI = QQIC    If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) -   +    0 1 2 3 4 5 6 7    +-+-+-+-+-+-+-+-+    |1| exp | mant  |    +-+-+-+-+-+-+-+-+ -   +    Since exp=0..7 then (exp+3)=3..10, then QQI has    one of the following bit patterns: -   +    exp=0: QQI = 0000.0000.1MMM.M000    exp=1: QQI = 0000.0001.MMMM.0000    ... @@ -48,33 +48,32 @@  */  uint8_t igmp_msg_encode16to8(uint16_t value)  { -  uint8_t code; - -  if (value < 128) { -    code = value; -  } -  else { -    uint16_t mask = 0x4000; -    uint8_t  exp; -    uint16_t mant; -    for (exp = 7; exp > 0; --exp) { -      if (mask & value) -	break; -      mask >>= 1; -    } -    mant = 0x000F & (value >> (exp + 3)); -    code = ((uint8_t) 1 << 7) | ((uint8_t) exp << 4) | (uint8_t) mant; -  } - -  return code; +	uint8_t code; + +	if (value < 128) { +		code = value; +	} else { +		uint16_t mask = 0x4000; +		uint8_t exp; +		uint16_t mant; +		for (exp = 7; exp > 0; --exp) { +			if (mask & value) +				break; +			mask >>= 1; +		} +		mant = 0x000F & (value >> (exp + 3)); +		code = ((uint8_t)1 << 7) | ((uint8_t)exp << 4) | (uint8_t)mant; +	} + +	return code;  }  /*    RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) -   +    If QQIC < 128,  QQI = QQIC    If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) -   +    0 1 2 3 4 5 6 7    +-+-+-+-+-+-+-+-+    |1| exp | mant  | @@ -82,64 +81,57 @@ uint8_t igmp_msg_encode16to8(uint16_t value)  */  uint16_t igmp_msg_decode8to16(uint8_t code)  { -  uint16_t value; - -  if (code < 128) { -    value = code; -  } -  else { -    uint16_t mant = (code & 0x0F); -    uint8_t  exp  = (code & 0x70) >> 4; -    value = (mant | 0x10) << (exp + 3); -  } - -  return value; +	uint16_t value; + +	if (code < 128) { +		value = code; +	} else { +		uint16_t mant = (code & 0x0F); +		uint8_t exp = (code & 0x70) >> 4; +		value = (mant | 0x10) << (exp + 3); +	} + +	return value;  }  void pim_pkt_dump(const char *label, const uint8_t *buf, int size)  { -  zlog_debug("%s: pkt dump size=%d", -	     label, -	     size); -  zlog_hexdump(buf, size); +	zlog_debug("%s: pkt dump size=%d", label, size); +	zlog_hexdump(buf, size);  } -int -pim_is_group_224_0_0_0_24 (struct in_addr group_addr) +int pim_is_group_224_0_0_0_24(struct in_addr group_addr)  { -  static int first = 1; -  static struct prefix group_224; -  struct prefix group; +	static int first = 1; +	static struct prefix group_224; +	struct prefix group; -  if (first) -    { -      str2prefix ("224.0.0.0/24", &group_224); -      first = 0; -    } +	if (first) { +		str2prefix("224.0.0.0/24", &group_224); +		first = 0; +	} -  group.family = AF_INET; -  group.u.prefix4 = group_addr; -  group.prefixlen = 32; +	group.family = AF_INET; +	group.u.prefix4 = group_addr; +	group.prefixlen = 32; -  return prefix_match (&group_224, &group); +	return prefix_match(&group_224, &group);  } -int -pim_is_group_224_4 (struct in_addr group_addr) +int pim_is_group_224_4(struct in_addr group_addr)  { -  static int first = 1; -  static struct prefix group_all; -  struct prefix group; +	static int first = 1; +	static struct prefix group_all; +	struct prefix group; -  if (first) -    { -      str2prefix ("224.0.0.0/4", &group_all); -      first = 0; -    } +	if (first) { +		str2prefix("224.0.0.0/4", &group_all); +		first = 0; +	} -  group.family = AF_INET; -  group.u.prefix4 = group_addr; -  group.prefixlen = 32; +	group.family = AF_INET; +	group.u.prefix4 = group_addr; +	group.prefixlen = 32; -  return prefix_match (&group_all, &group); +	return prefix_match(&group_all, &group);  } diff --git a/pimd/pim_util.h b/pimd/pim_util.h index 4788005206..1b319cfe4c 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -31,6 +31,6 @@ uint16_t igmp_msg_decode8to16(uint8_t code);  void pim_pkt_dump(const char *label, const uint8_t *buf, int size); -int pim_is_group_224_0_0_0_24 (struct in_addr group_addr); -int pim_is_group_224_4 (struct in_addr group_addr); +int pim_is_group_224_0_0_0_24(struct in_addr group_addr); +int pim_is_group_224_4(struct in_addr group_addr);  #endif /* PIM_UTIL_H */ diff --git a/pimd/pim_version.c b/pimd/pim_version.c index 1da4b9663f..439f745ac1 100644 --- a/pimd/pim_version.c +++ b/pimd/pim_version.c @@ -21,4 +21,4 @@  #include "pim_version.h" -const char * const PIMD_VERSION = PIMD_VERSION_STR; +const char *const PIMD_VERSION = PIMD_VERSION_STR; diff --git a/pimd/pim_version.h b/pimd/pim_version.h index 589c6f68a5..c45d01a13a 100644 --- a/pimd/pim_version.h +++ b/pimd/pim_version.h @@ -22,6 +22,6 @@  #define PIMD_VERSION_STR "0.166" -const char * const PIMD_VERSION; +const char *const PIMD_VERSION;  #endif /* PIM_VERSION_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 81b49c630c..a787767911 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -40,284 +40,287 @@  #include "pim_ssm.h"  #include "pim_bfd.h" -int -pim_debug_config_write (struct vty *vty) +int pim_debug_config_write(struct vty *vty)  { -  int writes = 0; - -  if (PIM_DEBUG_MSDP_EVENTS) { -    vty_out (vty, "debug msdp events\n"); -    ++writes; -  } -  if (PIM_DEBUG_MSDP_PACKETS) { -    vty_out (vty, "debug msdp packets\n"); -    ++writes; -  } -  if (PIM_DEBUG_MSDP_INTERNAL) { -    vty_out (vty, "debug msdp internal\n"); -    ++writes; -  } -  if (PIM_DEBUG_IGMP_EVENTS) { -    vty_out (vty, "debug igmp events\n"); -    ++writes; -  } -  if (PIM_DEBUG_IGMP_PACKETS) { -    vty_out (vty, "debug igmp packets\n"); -    ++writes; -  } -  if (PIM_DEBUG_IGMP_TRACE) { -    vty_out (vty, "debug igmp trace\n"); -    ++writes; -  } -  if (PIM_DEBUG_IGMP_TRACE_DETAIL) { -    vty_out (vty, "debug igmp trace detail\n"); -    ++writes; -  } - -  if (PIM_DEBUG_MROUTE) { -    vty_out (vty, "debug mroute\n"); -    ++writes; -  } - -  if (PIM_DEBUG_MROUTE_DETAIL) { -    vty_out (vty, "debug mroute detail\n"); -    ++writes; -  } - -  if (PIM_DEBUG_PIM_EVENTS) { -    vty_out (vty, "debug pim events\n"); -    ++writes; -  } -  if (PIM_DEBUG_PIM_PACKETS) { -    vty_out (vty, "debug pim packets\n"); -    ++writes; -  } -  if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { -    vty_out (vty, "debug pim packet-dump send\n"); -    ++writes; -  } -  if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { -    vty_out (vty, "debug pim packet-dump receive\n"); -    ++writes; -  } - -  if (PIM_DEBUG_PIM_TRACE) { -    vty_out (vty, "debug pim trace\n"); -    ++writes; -  } -  if (PIM_DEBUG_PIM_TRACE_DETAIL) { -    vty_out (vty, "debug pim trace detail\n"); -    ++writes; -  } - -  if (PIM_DEBUG_ZEBRA) { -    vty_out (vty, "debug pim zebra\n"); -    ++writes; -  } - -  if (PIM_DEBUG_SSMPINGD) { -    vty_out (vty, "debug ssmpingd\n"); -    ++writes; -  } - -  if (PIM_DEBUG_PIM_HELLO) { -    vty_out (vty, "debug pim packets hello\n"); -    ++writes; -  } - -  if (PIM_DEBUG_PIM_J_P) { -    vty_out (vty, "debug pim packets joins\n"); -    ++writes; -  } - -  if (PIM_DEBUG_PIM_REG) { -    vty_out (vty, "debug pim packets register\n"); -    ++writes; -  } - -  if (PIM_DEBUG_STATIC) { -    vty_out (vty, "debug pim static\n"); -    ++writes; -  } - -  return writes; +	int writes = 0; + +	if (PIM_DEBUG_MSDP_EVENTS) { +		vty_out(vty, "debug msdp events\n"); +		++writes; +	} +	if (PIM_DEBUG_MSDP_PACKETS) { +		vty_out(vty, "debug msdp packets\n"); +		++writes; +	} +	if (PIM_DEBUG_MSDP_INTERNAL) { +		vty_out(vty, "debug msdp internal\n"); +		++writes; +	} +	if (PIM_DEBUG_IGMP_EVENTS) { +		vty_out(vty, "debug igmp events\n"); +		++writes; +	} +	if (PIM_DEBUG_IGMP_PACKETS) { +		vty_out(vty, "debug igmp packets\n"); +		++writes; +	} +	if (PIM_DEBUG_IGMP_TRACE) { +		vty_out(vty, "debug igmp trace\n"); +		++writes; +	} +	if (PIM_DEBUG_IGMP_TRACE_DETAIL) { +		vty_out(vty, "debug igmp trace detail\n"); +		++writes; +	} + +	if (PIM_DEBUG_MROUTE) { +		vty_out(vty, "debug mroute\n"); +		++writes; +	} + +	if (PIM_DEBUG_MROUTE_DETAIL) { +		vty_out(vty, "debug mroute detail\n"); +		++writes; +	} + +	if (PIM_DEBUG_PIM_EVENTS) { +		vty_out(vty, "debug pim events\n"); +		++writes; +	} +	if (PIM_DEBUG_PIM_PACKETS) { +		vty_out(vty, "debug pim packets\n"); +		++writes; +	} +	if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { +		vty_out(vty, "debug pim packet-dump send\n"); +		++writes; +	} +	if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { +		vty_out(vty, "debug pim packet-dump receive\n"); +		++writes; +	} + +	if (PIM_DEBUG_PIM_TRACE) { +		vty_out(vty, "debug pim trace\n"); +		++writes; +	} +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		vty_out(vty, "debug pim trace detail\n"); +		++writes; +	} + +	if (PIM_DEBUG_ZEBRA) { +		vty_out(vty, "debug pim zebra\n"); +		++writes; +	} + +	if (PIM_DEBUG_SSMPINGD) { +		vty_out(vty, "debug ssmpingd\n"); +		++writes; +	} + +	if (PIM_DEBUG_PIM_HELLO) { +		vty_out(vty, "debug pim packets hello\n"); +		++writes; +	} + +	if (PIM_DEBUG_PIM_J_P) { +		vty_out(vty, "debug pim packets joins\n"); +		++writes; +	} + +	if (PIM_DEBUG_PIM_REG) { +		vty_out(vty, "debug pim packets register\n"); +		++writes; +	} + +	if (PIM_DEBUG_STATIC) { +		vty_out(vty, "debug pim static\n"); +		++writes; +	} + +	return writes;  }  int pim_global_config_write(struct vty *vty)  { -  int writes = 0; -  struct pim_ssm *ssm = pimg->ssm_info; - -  writes += pim_msdp_config_write (vty); - -  if (!pimg->send_v6_secondary) -    { -      vty_out (vty, "no ip pim send-v6-secondary\n"); -      ++writes; -    } - -  writes += pim_rp_config_write (vty); - -  if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) -    { -      vty_out (vty, "ip pim register-suppress-time %d\n", -	       qpim_register_suppress_time); -      ++writes; -    } -  if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) -    { -      vty_out (vty, "ip pim join-prune-interval %d\n", -	       qpim_t_periodic); -      ++writes; -    } -  if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) -    { -      vty_out (vty, "ip pim keep-alive-timer %d\n", -               qpim_keep_alive_time); -      ++writes; -    } -  if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) -    { -      vty_out (vty, "ip pim packets %d\n", -	       qpim_packet_process); -      ++writes; -    } -  if (ssm->plist_name) -    { -      vty_out (vty, "ip pim ssm prefix-list %s\n", -               ssm->plist_name); -      ++writes; -    } -  if (pimg->spt.switchover == PIM_SPT_INFINITY) -    { -      if (pimg->spt.plist) -        vty_out (vty, "ip pim spt-switchover infinity-and-beyond prefix-list %s\n", -                 pimg->spt.plist); -      else -        vty_out (vty,"ip pim spt-switchover infinity-and-beyond\n"); -      ++writes; -    } -  if (qpim_ecmp_rebalance_enable) -    { -      vty_out (vty, "ip pim ecmp rebalance\n"); -      ++writes; -    } -  else if (qpim_ecmp_enable) -    { -      vty_out (vty, "ip pim ecmp\n"); -      ++writes; -    } -  if (qpim_ssmpingd_list) { -    struct listnode *node; -    struct ssmpingd_sock *ss; -    vty_out (vty, "!\n"); -    ++writes; -    for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { -      char source_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str)); -      vty_out (vty, "ip ssmpingd %s\n", source_str); -      ++writes; -    } -  } - -  return writes; -} +	int writes = 0; +	struct pim_ssm *ssm = pimg->ssm_info; -int pim_interface_config_write(struct vty *vty) -{ -  int writes = 0; -  struct listnode *node; -  struct interface *ifp; - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - -    /* IF name */ -    vty_out (vty, "interface %s\n", ifp->name); -    ++writes; - -    if (ifp->info) { -      struct pim_interface *pim_ifp = ifp->info; - -      if (PIM_IF_TEST_PIM(pim_ifp->options)) { -	vty_out (vty, " ip pim sm\n"); -	++writes; -      } - -      /* IF ip pim drpriority */ -      if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { -	vty_out (vty, " ip pim drpriority %u\n",pim_ifp->pim_dr_priority); -	++writes; -      } - -      /* IF ip pim hello */ -      if (pim_ifp->pim_hello_period != PIM_DEFAULT_HELLO_PERIOD) { -	vty_out(vty, " ip pim hello %d", pim_ifp->pim_hello_period); -	if (pim_ifp->pim_default_holdtime != -1) -	  vty_out(vty, " %d", pim_ifp->pim_default_holdtime); -	vty_out (vty, "\n"); -      } - -      /* update source */ -      if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { -        char src_str[INET_ADDRSTRLEN]; -        pim_inet4_dump("<src?>", pim_ifp->update_source, src_str, -            sizeof(src_str)); -        vty_out (vty, " ip pim use-source %s\n", src_str); -        ++writes; -      } - -      /* IF ip igmp */ -      if (PIM_IF_TEST_IGMP(pim_ifp->options)) { -	vty_out (vty, " ip igmp\n"); -	++writes; -      } - -      /* ip igmp version */ -      if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) -        { -          vty_out (vty, " ip igmp version %d\n", -                  pim_ifp->igmp_version); -          ++writes; -        } - -      /* IF ip igmp query-interval */ -      if (pim_ifp->igmp_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL) -	{ -	  vty_out (vty, " ip igmp query-interval %d\n", -		  pim_ifp->igmp_default_query_interval); -	  ++writes; +	writes += pim_msdp_config_write(vty); + +	if (!pimg->send_v6_secondary) { +		vty_out(vty, "no ip pim send-v6-secondary\n"); +		++writes;  	} -      /* IF ip igmp query-max-response-time */ -      if (pim_ifp->igmp_query_max_response_time_dsec != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) -	{ -	  vty_out (vty, " ip igmp query-max-response-time %d\n", -		  pim_ifp->igmp_query_max_response_time_dsec); -	  ++writes; +	writes += pim_rp_config_write(vty); + +	if (qpim_register_suppress_time +	    != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) { +		vty_out(vty, "ip pim register-suppress-time %d\n", +			qpim_register_suppress_time); +		++writes;  	} +	if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) { +		vty_out(vty, "ip pim join-prune-interval %d\n", +			qpim_t_periodic); +		++writes; +	} +	if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) { +		vty_out(vty, "ip pim keep-alive-timer %d\n", +			qpim_keep_alive_time); +		++writes; +	} +	if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) { +		vty_out(vty, "ip pim packets %d\n", qpim_packet_process); +		++writes; +	} +	if (ssm->plist_name) { +		vty_out(vty, "ip pim ssm prefix-list %s\n", ssm->plist_name); +		++writes; +	} +	if (pimg->spt.switchover == PIM_SPT_INFINITY) { +		if (pimg->spt.plist) +			vty_out(vty, +				"ip pim spt-switchover infinity-and-beyond prefix-list %s\n", +				pimg->spt.plist); +		else +			vty_out(vty, +				"ip pim spt-switchover infinity-and-beyond\n"); +		++writes; +	} +	if (qpim_ecmp_rebalance_enable) { +		vty_out(vty, "ip pim ecmp rebalance\n"); +		++writes; +	} else if (qpim_ecmp_enable) { +		vty_out(vty, "ip pim ecmp\n"); +		++writes; +	} +	if (qpim_ssmpingd_list) { +		struct listnode *node; +		struct ssmpingd_sock *ss; +		vty_out(vty, "!\n"); +		++writes; +		for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { +			char source_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<src?>", ss->source_addr, source_str, +				       sizeof(source_str)); +			vty_out(vty, "ip ssmpingd %s\n", source_str); +			++writes; +		} +	} + +	return writes; +} -      /* IF ip igmp join */ -      if (pim_ifp->igmp_join_list) { +int pim_interface_config_write(struct vty *vty) +{ +	int writes = 0;  	struct listnode *node; -	struct igmp_join *ij; -	for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, node, ij)) { -	  char group_str[INET_ADDRSTRLEN]; -	  char source_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str)); -          inet_ntop(AF_INET, &ij->source_addr, source_str, sizeof(source_str)); -	  vty_out (vty, " ip igmp join %s %s\n", -		  group_str,source_str); -	  ++writes; +	struct interface *ifp; + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + +		/* IF name */ +		vty_out(vty, "interface %s\n", ifp->name); +		++writes; + +		if (ifp->info) { +			struct pim_interface *pim_ifp = ifp->info; + +			if (PIM_IF_TEST_PIM(pim_ifp->options)) { +				vty_out(vty, " ip pim sm\n"); +				++writes; +			} + +			/* IF ip pim drpriority */ +			if (pim_ifp->pim_dr_priority +			    != PIM_DEFAULT_DR_PRIORITY) { +				vty_out(vty, " ip pim drpriority %u\n", +					pim_ifp->pim_dr_priority); +				++writes; +			} + +			/* IF ip pim hello */ +			if (pim_ifp->pim_hello_period +			    != PIM_DEFAULT_HELLO_PERIOD) { +				vty_out(vty, " ip pim hello %d", +					pim_ifp->pim_hello_period); +				if (pim_ifp->pim_default_holdtime != -1) +					vty_out(vty, " %d", +						pim_ifp->pim_default_holdtime); +				vty_out(vty, "\n"); +			} + +			/* update source */ +			if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { +				char src_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<src?>", pim_ifp->update_source, +					       src_str, sizeof(src_str)); +				vty_out(vty, " ip pim use-source %s\n", +					src_str); +				++writes; +			} + +			/* IF ip igmp */ +			if (PIM_IF_TEST_IGMP(pim_ifp->options)) { +				vty_out(vty, " ip igmp\n"); +				++writes; +			} + +			/* ip igmp version */ +			if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) { +				vty_out(vty, " ip igmp version %d\n", +					pim_ifp->igmp_version); +				++writes; +			} + +			/* IF ip igmp query-interval */ +			if (pim_ifp->igmp_default_query_interval +			    != IGMP_GENERAL_QUERY_INTERVAL) { +				vty_out(vty, " ip igmp query-interval %d\n", +					pim_ifp->igmp_default_query_interval); +				++writes; +			} + +			/* IF ip igmp query-max-response-time */ +			if (pim_ifp->igmp_query_max_response_time_dsec +			    != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) { +				vty_out(vty, +					" ip igmp query-max-response-time %d\n", +					pim_ifp->igmp_query_max_response_time_dsec); +				++writes; +			} + +			/* IF ip igmp join */ +			if (pim_ifp->igmp_join_list) { +				struct listnode *node; +				struct igmp_join *ij; +				for (ALL_LIST_ELEMENTS_RO( +					     pim_ifp->igmp_join_list, node, +					     ij)) { +					char group_str[INET_ADDRSTRLEN]; +					char source_str[INET_ADDRSTRLEN]; +					pim_inet4_dump("<grp?>", ij->group_addr, +						       group_str, +						       sizeof(group_str)); +					inet_ntop(AF_INET, &ij->source_addr, +						  source_str, +						  sizeof(source_str)); +					vty_out(vty, " ip igmp join %s %s\n", +						group_str, source_str); +					++writes; +				} +			} + +			writes += pim_static_write_mroute(vty, ifp); +		} +		vty_out(vty, "!\n"); +		++writes; +		/* PIM BFD write */ +		pim_bfd_write_config(vty, ifp);  	} -      } - -	writes += pim_static_write_mroute (vty, ifp); -    } -    vty_out (vty, "!\n"); -    ++writes; -    /* PIM BFD write */ -    pim_bfd_write_config (vty, ifp); -  } -  return writes; +	return writes;  } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b4fff97120..c5cca7d1b4 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -58,906 +58,950 @@ static struct zclient *zclient = NULL;  static int pim_router_id_update_zebra(int command, struct zclient *zclient,  				      zebra_size_t length, vrf_id_t vrf_id)  { -  struct prefix router_id; +	struct prefix router_id; -  zebra_router_id_update_read(zclient->ibuf, &router_id); +	zebra_router_id_update_read(zclient->ibuf, &router_id); -  return 0; +	return 0;  }  static int pim_zebra_if_add(int command, struct zclient *zclient,  			    zebra_size_t length, vrf_id_t vrf_id)  { -  struct interface *ifp; - -  /* -    zebra api adds/dels interfaces using the same call -    interface_add_read below, see comments in lib/zclient.c -  */ -  ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); -  if (!ifp) -    return 0; - -  if (PIM_DEBUG_ZEBRA) { -    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", -	       __PRETTY_FUNCTION__, -	       ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, -	       ifp->mtu, if_is_operative(ifp)); -  } - -  if (if_is_operative(ifp)) -    pim_if_addr_add_all(ifp); - -  return 0; +	struct interface *ifp; + +	/* +	  zebra api adds/dels interfaces using the same call +	  interface_add_read below, see comments in lib/zclient.c +	*/ +	ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); +	if (!ifp) +		return 0; + +	if (PIM_DEBUG_ZEBRA) { +		zlog_debug( +			"%s: %s index %d flags %ld metric %d mtu %d operative %d", +			__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, +			(long)ifp->flags, ifp->metric, ifp->mtu, +			if_is_operative(ifp)); +	} + +	if (if_is_operative(ifp)) +		pim_if_addr_add_all(ifp); + +	return 0;  }  static int pim_zebra_if_del(int command, struct zclient *zclient,  			    zebra_size_t length, vrf_id_t vrf_id)  { -  struct interface *ifp; - -  /* -    zebra api adds/dels interfaces using the same call -    interface_add_read below, see comments in lib/zclient.c -     -    comments in lib/zclient.c seem to indicate that calling -    zebra_interface_add_read is the correct call, but that -    results in an attemted out of bounds read which causes -    pimd to assert. Other clients use zebra_interface_state_read -    and it appears to work just fine. -  */ -  ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); -  if (!ifp) -    return 0; - -  if (PIM_DEBUG_ZEBRA) { -    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", -	       __PRETTY_FUNCTION__, -	       ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, -	       ifp->mtu, if_is_operative(ifp)); -  } - -  if (!if_is_operative(ifp)) -    pim_if_addr_del_all(ifp); - -  return 0; +	struct interface *ifp; + +	/* +	  zebra api adds/dels interfaces using the same call +	  interface_add_read below, see comments in lib/zclient.c + +	  comments in lib/zclient.c seem to indicate that calling +	  zebra_interface_add_read is the correct call, but that +	  results in an attemted out of bounds read which causes +	  pimd to assert. Other clients use zebra_interface_state_read +	  and it appears to work just fine. +	*/ +	ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); +	if (!ifp) +		return 0; + +	if (PIM_DEBUG_ZEBRA) { +		zlog_debug( +			"%s: %s index %d flags %ld metric %d mtu %d operative %d", +			__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, +			(long)ifp->flags, ifp->metric, ifp->mtu, +			if_is_operative(ifp)); +	} + +	if (!if_is_operative(ifp)) +		pim_if_addr_del_all(ifp); + +	return 0;  }  static int pim_zebra_if_state_up(int command, struct zclient *zclient,  				 zebra_size_t length, vrf_id_t vrf_id)  { -  struct interface *ifp; - -  /* -    zebra api notifies interface up/down events by using the same call -    zebra_interface_state_read below, see comments in lib/zclient.c -  */ -  ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); -  if (!ifp) -    return 0; - -  if (PIM_DEBUG_ZEBRA) { -    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", -	       __PRETTY_FUNCTION__, -	       ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, -	       ifp->mtu, if_is_operative(ifp)); -  } - -  if (if_is_operative(ifp)) { -    /* -      pim_if_addr_add_all() suffices for bringing up both IGMP and PIM -    */ -    pim_if_addr_add_all(ifp); -  } - -  return 0; +	struct interface *ifp; + +	/* +	  zebra api notifies interface up/down events by using the same call +	  zebra_interface_state_read below, see comments in lib/zclient.c +	*/ +	ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); +	if (!ifp) +		return 0; + +	if (PIM_DEBUG_ZEBRA) { +		zlog_debug( +			"%s: %s index %d flags %ld metric %d mtu %d operative %d", +			__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, +			(long)ifp->flags, ifp->metric, ifp->mtu, +			if_is_operative(ifp)); +	} + +	if (if_is_operative(ifp)) { +		/* +		  pim_if_addr_add_all() suffices for bringing up both IGMP and +		  PIM +		*/ +		pim_if_addr_add_all(ifp); +	} + +	return 0;  }  static int pim_zebra_if_state_down(int command, struct zclient *zclient,  				   zebra_size_t length, vrf_id_t vrf_id)  { -  struct interface *ifp; - -  /* -    zebra api notifies interface up/down events by using the same call -    zebra_interface_state_read below, see comments in lib/zclient.c -  */ -  ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); -  if (!ifp) -    return 0; - -  if (PIM_DEBUG_ZEBRA) { -    zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", -	       __PRETTY_FUNCTION__, -	       ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, -	       ifp->mtu, if_is_operative(ifp)); -  } - -  if (!if_is_operative(ifp)) { -    pim_ifchannel_delete_all(ifp); -    /* -      pim_if_addr_del_all() suffices for shutting down IGMP, -      but not for shutting down PIM -    */ -    pim_if_addr_del_all(ifp); - -    /* -      pim_sock_delete() closes the socket, stops read and timer threads, -      and kills all neighbors. -    */ -    if (ifp->info) { -      pim_sock_delete(ifp, "link down"); -    } -  } - -  if (ifp->info) -    pim_if_del_vif(ifp); - -  return 0; +	struct interface *ifp; + +	/* +	  zebra api notifies interface up/down events by using the same call +	  zebra_interface_state_read below, see comments in lib/zclient.c +	*/ +	ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); +	if (!ifp) +		return 0; + +	if (PIM_DEBUG_ZEBRA) { +		zlog_debug( +			"%s: %s index %d flags %ld metric %d mtu %d operative %d", +			__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, +			(long)ifp->flags, ifp->metric, ifp->mtu, +			if_is_operative(ifp)); +	} + +	if (!if_is_operative(ifp)) { +		pim_ifchannel_delete_all(ifp); +		/* +		  pim_if_addr_del_all() suffices for shutting down IGMP, +		  but not for shutting down PIM +		*/ +		pim_if_addr_del_all(ifp); + +		/* +		  pim_sock_delete() closes the socket, stops read and timer +		  threads, +		  and kills all neighbors. +		*/ +		if (ifp->info) { +			pim_sock_delete(ifp, "link down"); +		} +	} + +	if (ifp->info) +		pim_if_del_vif(ifp); + +	return 0;  }  #ifdef PIM_DEBUG_IFADDR_DUMP  static void dump_if_address(struct interface *ifp)  { -  struct connected *ifc; -  struct listnode *node; - -  zlog_debug("%s %s: interface %s addresses:", -	     __FILE__, __PRETTY_FUNCTION__, -	     ifp->name); -   -  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { -    struct prefix *p = ifc->address; -     -    if (p->family != AF_INET) -      continue; -     -    zlog_debug("%s %s: interface %s address %s %s", -	       __FILE__, __PRETTY_FUNCTION__, -	       ifp->name, -	       inet_ntoa(p->u.prefix4), -	       CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?  -	       "secondary" : "primary"); -  } +	struct connected *ifc; +	struct listnode *node; + +	zlog_debug("%s %s: interface %s addresses:", __FILE__, +		   __PRETTY_FUNCTION__, ifp->name); + +	for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { +		struct prefix *p = ifc->address; + +		if (p->family != AF_INET) +			continue; + +		zlog_debug("%s %s: interface %s address %s %s", __FILE__, +			   __PRETTY_FUNCTION__, ifp->name, +			   inet_ntoa(p->u.prefix4), +			   CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) +				   ? "secondary" +				   : "primary"); +	}  }  #endif  static int pim_zebra_if_address_add(int command, struct zclient *zclient,  				    zebra_size_t length, vrf_id_t vrf_id)  { -  struct connected *c; -  struct prefix *p; -  struct pim_interface *pim_ifp; - -  /* -    zebra api notifies address adds/dels events by using the same call -    interface_add_read below, see comments in lib/zclient.c - -    zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...) -    will add address to interface list by calling -    connected_add_by_prefix() -  */ -  c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); -  if (!c) -    return 0; - -  pim_ifp = c->ifp->info; -  p = c->address; - -  if (PIM_DEBUG_ZEBRA) { -    char buf[BUFSIZ]; -    prefix2str(p, buf, BUFSIZ); -    zlog_debug("%s: %s connected IP address %s flags %u %s", -	       __PRETTY_FUNCTION__, -	       c->ifp->name, buf, c->flags, -	       CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); -     +	struct connected *c; +	struct prefix *p; +	struct pim_interface *pim_ifp; + +	/* +	  zebra api notifies address adds/dels events by using the same call +	  interface_add_read below, see comments in lib/zclient.c + +	  zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...) +	  will add address to interface list by calling +	  connected_add_by_prefix() +	*/ +	c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); +	if (!c) +		return 0; + +	pim_ifp = c->ifp->info; +	p = c->address; + +	if (PIM_DEBUG_ZEBRA) { +		char buf[BUFSIZ]; +		prefix2str(p, buf, BUFSIZ); +		zlog_debug("%s: %s connected IP address %s flags %u %s", +			   __PRETTY_FUNCTION__, c->ifp->name, buf, c->flags, +			   CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) +				   ? "secondary" +				   : "primary"); +  #ifdef PIM_DEBUG_IFADDR_DUMP -    dump_if_address(c->ifp); +		dump_if_address(c->ifp);  #endif -  } +	} -  if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { -    /* trying to add primary address */ +	if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { +		/* trying to add primary address */ -    struct in_addr primary_addr = pim_find_primary_addr(c->ifp); -    if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) { -      if (PIM_DEBUG_ZEBRA) { -	/* but we had a primary address already */ +		struct in_addr primary_addr = pim_find_primary_addr(c->ifp); +		if (p->family != AF_INET +		    || primary_addr.s_addr != p->u.prefix4.s_addr) { +			if (PIM_DEBUG_ZEBRA) { +				/* but we had a primary address already */ -	char buf[BUFSIZ]; +				char buf[BUFSIZ]; -	prefix2str(p, buf, BUFSIZ); +				prefix2str(p, buf, BUFSIZ); -	zlog_warn("%s: %s : forcing secondary flag on %s", -		  __PRETTY_FUNCTION__, -		  c->ifp->name, buf); -      } -      SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY); -    } -  } +				zlog_warn( +					"%s: %s : forcing secondary flag on %s", +					__PRETTY_FUNCTION__, c->ifp->name, buf); +			} +			SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY); +		} +	} -  pim_if_addr_add(c); -  if (pim_ifp) -    pim_rp_check_on_if_add(pim_ifp); +	pim_if_addr_add(c); +	if (pim_ifp) +		pim_rp_check_on_if_add(pim_ifp); -  if (if_is_loopback (c->ifp)) -    { -      struct listnode *ifnode; -      struct interface *ifp; +	if (if_is_loopback(c->ifp)) { +		struct listnode *ifnode; +		struct interface *ifp; -      for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) -        { -	  if (!if_is_loopback (ifp) && if_is_operative (ifp)) -	    pim_if_addr_add_all (ifp); -        } -    } +		for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, +					  ifp)) { +			if (!if_is_loopback(ifp) && if_is_operative(ifp)) +				pim_if_addr_add_all(ifp); +		} +	} -  return 0; +	return 0;  }  static int pim_zebra_if_address_del(int command, struct zclient *client,  				    zebra_size_t length, vrf_id_t vrf_id)  { -  struct connected *c; -  struct prefix *p; - -  /* -    zebra api notifies address adds/dels events by using the same call -    interface_add_read below, see comments in lib/zclient.c - -    zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...) -    will remove address from interface list by calling -    connected_delete_by_prefix() -  */ -  c = zebra_interface_address_read(command, client->ibuf, vrf_id); -  if (!c) -    return 0; -   -  p = c->address; -  if (p->family == AF_INET) -    { -        if (PIM_DEBUG_ZEBRA) { -          char buf[BUFSIZ]; -          prefix2str(p, buf, BUFSIZ); -          zlog_debug("%s: %s disconnected IP address %s flags %u %s", -                     __PRETTY_FUNCTION__, -                     c->ifp->name, buf, c->flags, -                     CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); +	struct connected *c; +	struct prefix *p; + +	/* +	  zebra api notifies address adds/dels events by using the same call +	  interface_add_read below, see comments in lib/zclient.c + +	  zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...) +	  will remove address from interface list by calling +	  connected_delete_by_prefix() +	*/ +	c = zebra_interface_address_read(command, client->ibuf, vrf_id); +	if (!c) +		return 0; + +	p = c->address; +	if (p->family == AF_INET) { +		if (PIM_DEBUG_ZEBRA) { +			char buf[BUFSIZ]; +			prefix2str(p, buf, BUFSIZ); +			zlog_debug( +				"%s: %s disconnected IP address %s flags %u %s", +				__PRETTY_FUNCTION__, c->ifp->name, buf, +				c->flags, +				CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) +					? "secondary" +					: "primary");  #ifdef PIM_DEBUG_IFADDR_DUMP -          dump_if_address(c->ifp); +			dump_if_address(c->ifp);  #endif -        } +		} -        pim_if_addr_del(c, 0); -        pim_rp_setup(); -        pim_i_am_rp_re_evaluate(); -    } +		pim_if_addr_del(c, 0); +		pim_rp_setup(); +		pim_i_am_rp_re_evaluate(); +	} -  connected_free (c); -  return 0; +	connected_free(c); +	return 0;  }  static void scan_upstream_rpf_cache()  { -  struct listnode     *up_node; -  struct listnode     *ifnode; -  struct listnode     *up_nextnode; -  struct listnode     *node; -  struct pim_upstream *up; -  struct interface    *ifp; - -  for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { -    enum pim_rpf_result rpf_result; -    struct pim_rpf      old; -    struct prefix nht_p; - -    nht_p.family = AF_INET; -    nht_p.prefixlen = IPV4_MAX_BITLEN; -    nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; -    pim_resolve_upstream_nh (&nht_p); - -    old.source_nexthop.interface = up->rpf.source_nexthop.interface; -    old.source_nexthop.nbr       = up->rpf.source_nexthop.nbr; -    rpf_result = pim_rpf_update(up, &old, 0); - -    if (rpf_result == PIM_RPF_FAILURE) -      continue; - -    if (rpf_result == PIM_RPF_CHANGED) { -      struct pim_neighbor *nbr; - -      nbr = pim_neighbor_find (old.source_nexthop.interface, -                               old.rpf_addr.u.prefix4); -      if (nbr) -        pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - -      /* -       * We have detected a case where we might need to rescan -       * the inherited o_list so do it. -       */ -      if (up->channel_oil->oil_inherited_rescan) -	{ -	  pim_upstream_inherited_olist_decide (up); -	  up->channel_oil->oil_inherited_rescan = 0; -	} - -      if (up->join_state == PIM_UPSTREAM_JOINED) { -	/* -         * If we come up real fast we can be here -	 * where the mroute has not been installed -	 * so install it. -	 */ -	if (!up->channel_oil->installed) -	  pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - -        /* -         * RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Messages -         * -         * Transitions from Joined State -         * -         * RPF'(S,G) changes not due to an Assert -         * -         * The upstream (S,G) state machine remains in Joined -         * state. Send Join(S,G) to the new upstream neighbor, which is -         * the new value of RPF'(S,G).  Send Prune(S,G) to the old -         * upstream neighbor, which is the old value of RPF'(S,G).  Set -         * the Join Timer (JT) to expire after t_periodic seconds. -         */ -        pim_jp_agg_switch_interface (&old, &up->rpf, up); - -        pim_upstream_join_timer_restart(up, &old); -      } /* up->join_state == PIM_UPSTREAM_JOINED */ - -      /* FIXME can join_desired actually be changed by pim_rpf_update() -	 returning PIM_RPF_CHANGED ? */ -      pim_upstream_update_join_desired(up); - -    } /* PIM_RPF_CHANGED */ - -  } /* for (qpim_upstream_list) */ - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) -    if (ifp->info) -      { -        struct pim_interface *pim_ifp = ifp->info; -        struct pim_iface_upstream_switch *us; - -        for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node, us)) -          { -            struct pim_rpf rpf; -            rpf.source_nexthop.interface = ifp; -            rpf.rpf_addr.u.prefix4 = us->address; -            pim_joinprune_send(&rpf, us->us); -            pim_jp_agg_clear_group(us->us); -          } -      } +	struct listnode *up_node; +	struct listnode *ifnode; +	struct listnode *up_nextnode; +	struct listnode *node; +	struct pim_upstream *up; +	struct interface *ifp; + +	for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { +		enum pim_rpf_result rpf_result; +		struct pim_rpf old; +		struct prefix nht_p; + +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; +		pim_resolve_upstream_nh(&nht_p); + +		old.source_nexthop.interface = up->rpf.source_nexthop.interface; +		old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; +		rpf_result = pim_rpf_update(up, &old, 0); + +		if (rpf_result == PIM_RPF_FAILURE) +			continue; + +		if (rpf_result == PIM_RPF_CHANGED) { +			struct pim_neighbor *nbr; + +			nbr = pim_neighbor_find(old.source_nexthop.interface, +						old.rpf_addr.u.prefix4); +			if (nbr) +				pim_jp_agg_remove_group(nbr->upstream_jp_agg, +							up); + +			/* +			 * We have detected a case where we might need to rescan +			 * the inherited o_list so do it. +			 */ +			if (up->channel_oil->oil_inherited_rescan) { +				pim_upstream_inherited_olist_decide(up); +				up->channel_oil->oil_inherited_rescan = 0; +			} + +			if (up->join_state == PIM_UPSTREAM_JOINED) { +				/* +				 * If we come up real fast we can be here +				 * where the mroute has not been installed +				 * so install it. +				 */ +				if (!up->channel_oil->installed) +					pim_mroute_add(up->channel_oil, +						       __PRETTY_FUNCTION__); + +				/* +				 * RFC 4601: 4.5.7.  Sending (S,G) Join/Prune +				 * Messages +				 * +				 * Transitions from Joined State +				 * +				 * RPF'(S,G) changes not due to an Assert +				 * +				 * The upstream (S,G) state machine remains in +				 * Joined +				 * state. Send Join(S,G) to the new upstream +				 * neighbor, which is +				 * the new value of RPF'(S,G).  Send Prune(S,G) +				 * to the old +				 * upstream neighbor, which is the old value of +				 * RPF'(S,G).  Set +				 * the Join Timer (JT) to expire after +				 * t_periodic seconds. +				 */ +				pim_jp_agg_switch_interface(&old, &up->rpf, up); + +				pim_upstream_join_timer_restart(up, &old); +			} /* up->join_state == PIM_UPSTREAM_JOINED */ + +			/* FIXME can join_desired actually be changed by +			   pim_rpf_update() +			   returning PIM_RPF_CHANGED ? */ +			pim_upstream_update_join_desired(up); + +		} /* PIM_RPF_CHANGED */ + +	} /* for (qpim_upstream_list) */ + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) +		if (ifp->info) { +			struct pim_interface *pim_ifp = ifp->info; +			struct pim_iface_upstream_switch *us; + +			for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, +						  node, us)) { +				struct pim_rpf rpf; +				rpf.source_nexthop.interface = ifp; +				rpf.rpf_addr.u.prefix4 = us->address; +				pim_joinprune_send(&rpf, us->us); +				pim_jp_agg_clear_group(us->us); +			} +		}  } -void -pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index) +void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)  { -  struct in_addr vif_source; -  int input_iface_vif_index; -  int old_vif_index; - -  if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin, c_oil->oil.mfcc_mcastgrp)) -    return; - -  if (in_vif_index) -    input_iface_vif_index = in_vif_index; -  else -    { -      struct prefix src, grp; - -      src.family = AF_INET; -      src.prefixlen = IPV4_MAX_BITLEN; -      src.u.prefix4 = vif_source; -      grp.family = AF_INET; -      grp.prefixlen = IPV4_MAX_BITLEN; -      grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp; - -      if (PIM_DEBUG_ZEBRA) -        { -          char source_str[INET_ADDRSTRLEN]; -          char group_str[INET_ADDRSTRLEN]; -          pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -          pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -          zlog_debug ("%s: channel_oil (%s, %s) upstream info is not present.", -                      __PRETTY_FUNCTION__, source_str, group_str); -        } -      input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp); -    } - -  if (input_iface_vif_index < 1) -    { -      if (PIM_DEBUG_ZEBRA) -        { -          char source_str[INET_ADDRSTRLEN]; -          char group_str[INET_ADDRSTRLEN]; -          pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -          pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -          zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", -		     __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, -		     source_str, group_str); -        } -      pim_mroute_del (c_oil, __PRETTY_FUNCTION__); -      return; -    } - -  if (input_iface_vif_index == c_oil->oil.mfcc_parent) -    { -      if (!c_oil->installed) -        pim_mroute_add (c_oil, __PRETTY_FUNCTION__); - -      /* RPF unchanged */ -      return; -    } - -  if (PIM_DEBUG_ZEBRA) -    { -      struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); -      struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); -      char source_str[INET_ADDRSTRLEN]; -      char group_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -      pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -      zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", -		 __FILE__, __PRETTY_FUNCTION__, -		 source_str, group_str, -		 old_iif->name, c_oil->oil.mfcc_parent, -		 new_iif->name, input_iface_vif_index); -    } - -  /* new iif loops to existing oif ? */ -  if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) -    { -      struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - -      if (PIM_DEBUG_ZEBRA) { -	char source_str[INET_ADDRSTRLEN]; -	char group_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", -		   __FILE__, __PRETTY_FUNCTION__, -		   source_str, group_str, -		   new_iif->name, input_iface_vif_index); -      } -    } - -    /* update iif vif_index */ -    old_vif_index = c_oil->oil.mfcc_parent; -    c_oil->oil.mfcc_parent = input_iface_vif_index; - -    /* update kernel multicast forwarding cache (MFC) */ -    if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) -      { -	if (PIM_DEBUG_MROUTE) -	  { -	    /* just log warning */ -	    struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); -	    struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); -	    char source_str[INET_ADDRSTRLEN]; -	    char group_str[INET_ADDRSTRLEN]; -	    pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); -	    pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); -	    zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", -		       __FILE__, __PRETTY_FUNCTION__, -		       source_str, group_str, -		       old_iif ? old_iif->name : "<old_iif?>", c_oil->oil.mfcc_parent, -		       new_iif ? new_iif->name : "<new_iif?>", input_iface_vif_index); -	  } -    } +	struct in_addr vif_source; +	int input_iface_vif_index; +	int old_vif_index; + +	if (!pim_rp_set_upstream_addr(&vif_source, c_oil->oil.mfcc_origin, +				      c_oil->oil.mfcc_mcastgrp)) +		return; + +	if (in_vif_index) +		input_iface_vif_index = in_vif_index; +	else { +		struct prefix src, grp; + +		src.family = AF_INET; +		src.prefixlen = IPV4_MAX_BITLEN; +		src.u.prefix4 = vif_source; +		grp.family = AF_INET; +		grp.prefixlen = IPV4_MAX_BITLEN; +		grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp; + +		if (PIM_DEBUG_ZEBRA) { +			char source_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, +				       source_str, sizeof(source_str)); +			pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			zlog_debug( +				"%s: channel_oil (%s, %s) upstream info is not present.", +				__PRETTY_FUNCTION__, source_str, group_str); +		} +		input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index( +			vif_source, &src, &grp); +	} + +	if (input_iface_vif_index < 1) { +		if (PIM_DEBUG_ZEBRA) { +			char source_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, +				       source_str, sizeof(source_str)); +			pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			zlog_debug( +				"%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", +				__FILE__, __PRETTY_FUNCTION__, +				c_oil->oil.mfcc_parent, source_str, group_str); +		} +		pim_mroute_del(c_oil, __PRETTY_FUNCTION__); +		return; +	} + +	if (input_iface_vif_index == c_oil->oil.mfcc_parent) { +		if (!c_oil->installed) +			pim_mroute_add(c_oil, __PRETTY_FUNCTION__); + +		/* RPF unchanged */ +		return; +	} + +	if (PIM_DEBUG_ZEBRA) { +		struct interface *old_iif = +			pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); +		struct interface *new_iif = +			pim_if_find_by_vif_index(input_iface_vif_index); +		char source_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, +			       sizeof(source_str)); +		pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, +			       sizeof(group_str)); +		zlog_debug( +			"%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", +			__FILE__, __PRETTY_FUNCTION__, source_str, group_str, +			old_iif->name, c_oil->oil.mfcc_parent, new_iif->name, +			input_iface_vif_index); +	} + +	/* new iif loops to existing oif ? */ +	if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) { +		struct interface *new_iif = +			pim_if_find_by_vif_index(input_iface_vif_index); + +		if (PIM_DEBUG_ZEBRA) { +			char source_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, +				       source_str, sizeof(source_str)); +			pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			zlog_debug( +				"%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", +				__FILE__, __PRETTY_FUNCTION__, source_str, +				group_str, new_iif->name, +				input_iface_vif_index); +		} +	} + +	/* update iif vif_index */ +	old_vif_index = c_oil->oil.mfcc_parent; +	c_oil->oil.mfcc_parent = input_iface_vif_index; + +	/* update kernel multicast forwarding cache (MFC) */ +	if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { +		if (PIM_DEBUG_MROUTE) { +			/* just log warning */ +			struct interface *old_iif = +				pim_if_find_by_vif_index(old_vif_index); +			struct interface *new_iif = +				pim_if_find_by_vif_index(input_iface_vif_index); +			char source_str[INET_ADDRSTRLEN]; +			char group_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, +				       source_str, sizeof(source_str)); +			pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, +				       group_str, sizeof(group_str)); +			zlog_debug( +				"%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", +				__FILE__, __PRETTY_FUNCTION__, source_str, +				group_str, +				old_iif ? old_iif->name : "<old_iif?>", +				c_oil->oil.mfcc_parent, +				new_iif ? new_iif->name : "<new_iif?>", +				input_iface_vif_index); +		} +	}  }  void pim_scan_oil()  { -  struct listnode    *node; -  struct listnode    *nextnode; -  struct channel_oil *c_oil; -  ifindex_t          ifindex; -  int                vif_index = 0; - -  qpim_scan_oil_last = pim_time_monotonic_sec(); -  ++qpim_scan_oil_events; - -  for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) -    { -      if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) -        { -          ifindex = c_oil->up->rpf.source_nexthop.interface->ifindex; -          vif_index = pim_if_find_vifindex_by_ifindex (ifindex); -          /* Pass Current selected NH vif index to mroute download */ -          if (vif_index) -            pim_scan_individual_oil (c_oil, vif_index); -        } -      else -        pim_scan_individual_oil (c_oil, 0); -    } +	struct listnode *node; +	struct listnode *nextnode; +	struct channel_oil *c_oil; +	ifindex_t ifindex; +	int vif_index = 0; + +	qpim_scan_oil_last = pim_time_monotonic_sec(); +	++qpim_scan_oil_events; + +	for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) { +		if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) { +			ifindex = c_oil->up->rpf.source_nexthop +					  .interface->ifindex; +			vif_index = pim_if_find_vifindex_by_ifindex(ifindex); +			/* Pass Current selected NH vif index to mroute download +			 */ +			if (vif_index) +				pim_scan_individual_oil(c_oil, vif_index); +		} else +			pim_scan_individual_oil(c_oil, 0); +	}  }  static int on_rpf_cache_refresh(struct thread *t)  { -  /* update PIM protocol state */ -  scan_upstream_rpf_cache(); +	/* update PIM protocol state */ +	scan_upstream_rpf_cache(); -  /* update kernel multicast forwarding cache (MFC) */ -  pim_scan_oil(); +	/* update kernel multicast forwarding cache (MFC) */ +	pim_scan_oil(); -  qpim_rpf_cache_refresh_last = pim_time_monotonic_sec(); -  ++qpim_rpf_cache_refresh_events; +	qpim_rpf_cache_refresh_last = pim_time_monotonic_sec(); +	++qpim_rpf_cache_refresh_events; -  //It is called as part of pim_neighbor_add -  //pim_rp_setup (); -  return 0; +	// It is called as part of pim_neighbor_add +	// pim_rp_setup (); +	return 0;  }  void sched_rpf_cache_refresh(void)  { -  ++qpim_rpf_cache_refresh_requests; +	++qpim_rpf_cache_refresh_requests; -  pim_rpf_set_refresh_time (); +	pim_rpf_set_refresh_time(); -  if (qpim_rpf_cache_refresher) { -    /* Refresh timer is already running */ -    return; -  } +	if (qpim_rpf_cache_refresher) { +		/* Refresh timer is already running */ +		return; +	} -  /* Start refresh timer */ +	/* Start refresh timer */ -  if (PIM_DEBUG_ZEBRA) { -    zlog_debug("%s: triggering %ld msec timer", -               __PRETTY_FUNCTION__, -               qpim_rpf_cache_refresh_delay_msec); -  } +	if (PIM_DEBUG_ZEBRA) { +		zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__, +			   qpim_rpf_cache_refresh_delay_msec); +	} -  thread_add_timer_msec(master, on_rpf_cache_refresh, 0, -                        qpim_rpf_cache_refresh_delay_msec, -                        &qpim_rpf_cache_refresher); +	thread_add_timer_msec(master, on_rpf_cache_refresh, 0, +			      qpim_rpf_cache_refresh_delay_msec, +			      &qpim_rpf_cache_refresher);  } -static void -pim_zebra_connected (struct zclient *zclient) +static void pim_zebra_connected(struct zclient *zclient)  { -  /* Send the client registration */ -  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); +	/* Send the client registration */ +	bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); -  zclient_send_reg_requests (zclient, VRF_DEFAULT); +	zclient_send_reg_requests(zclient, VRF_DEFAULT);  }  void pim_zebra_init(void)  { -  int i; +	int i;  #ifdef HAVE_TCP_ZEBRA -  zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT); +	zlog_notice( +		"zclient update contacting ZEBRA daemon at socket TCP %s,%d", +		"127.0.0.1", ZEBRA_PORT);  #else -  zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get()); +	zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", +		    zclient_serv_path_get());  #endif -  /* Socket for receiving updates from Zebra daemon */ -  zclient = zclient_new (master); - -  zclient->zebra_connected          = pim_zebra_connected; -  zclient->router_id_update         = pim_router_id_update_zebra; -  zclient->interface_add            = pim_zebra_if_add; -  zclient->interface_delete         = pim_zebra_if_del; -  zclient->interface_up             = pim_zebra_if_state_up; -  zclient->interface_down           = pim_zebra_if_state_down; -  zclient->interface_address_add    = pim_zebra_if_address_add; -  zclient->interface_address_delete = pim_zebra_if_address_del; -  zclient->nexthop_update           = pim_parse_nexthop_update; - -  zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_info("zclient_init cleared redistribution request"); -  } - -  zassert(zclient->redist_default == ZEBRA_ROUTE_PIM); - -  /* Request all redistribution */ -  for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { -    if (i == zclient->redist_default) -      continue; -    vrf_bitmap_set (zclient->redist[AFI_IP][i], VRF_DEFAULT);; -    if (PIM_DEBUG_PIM_TRACE) { -      zlog_debug("%s: requesting redistribution for %s (%i)",  -		 __PRETTY_FUNCTION__, zebra_route_string(i), i); -    } -  } - -  /* Request default information */ -  zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, -				zclient, VRF_DEFAULT); -   -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_info("%s: requesting default information redistribution", -	      __PRETTY_FUNCTION__); - -    zlog_notice("%s: zclient update socket initialized", -		__PRETTY_FUNCTION__); -  } - -  zclient_lookup_new(); +	/* Socket for receiving updates from Zebra daemon */ +	zclient = zclient_new(master); + +	zclient->zebra_connected = pim_zebra_connected; +	zclient->router_id_update = pim_router_id_update_zebra; +	zclient->interface_add = pim_zebra_if_add; +	zclient->interface_delete = pim_zebra_if_del; +	zclient->interface_up = pim_zebra_if_state_up; +	zclient->interface_down = pim_zebra_if_state_down; +	zclient->interface_address_add = pim_zebra_if_address_add; +	zclient->interface_address_delete = pim_zebra_if_address_del; +	zclient->nexthop_update = pim_parse_nexthop_update; + +	zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_info("zclient_init cleared redistribution request"); +	} + +	zassert(zclient->redist_default == ZEBRA_ROUTE_PIM); + +	/* Request all redistribution */ +	for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { +		if (i == zclient->redist_default) +			continue; +		vrf_bitmap_set(zclient->redist[AFI_IP][i], VRF_DEFAULT); +		; +		if (PIM_DEBUG_PIM_TRACE) { +			zlog_debug("%s: requesting redistribution for %s (%i)", +				   __PRETTY_FUNCTION__, zebra_route_string(i), +				   i); +		} +	} + +	/* Request default information */ +	zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, +				     VRF_DEFAULT); + +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_info("%s: requesting default information redistribution", +			  __PRETTY_FUNCTION__); + +		zlog_notice("%s: zclient update socket initialized", +			    __PRETTY_FUNCTION__); +	} + +	zclient_lookup_new();  }  void igmp_anysource_forward_start(struct igmp_group *group)  { -  struct igmp_source *source; -  struct in_addr src_addr = { .s_addr = 0 }; -  /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ -  zassert(group->group_filtermode_isexcl); -  zassert(listcount(group->group_source_list) < 1); - -  source = source_new (group, src_addr); -  if (!source) -    { -      zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__); -      return; -    } - -  igmp_source_forward_start (source); +	struct igmp_source *source; +	struct in_addr src_addr = {.s_addr = 0}; +	/* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ +	zassert(group->group_filtermode_isexcl); +	zassert(listcount(group->group_source_list) < 1); + +	source = source_new(group, src_addr); +	if (!source) { +		zlog_warn("%s: Failure to create * source", +			  __PRETTY_FUNCTION__); +		return; +	} + +	igmp_source_forward_start(source);  }  void igmp_anysource_forward_stop(struct igmp_group *group)  { -  struct igmp_source *source; -  struct in_addr star = { .s_addr = 0 }; +	struct igmp_source *source; +	struct in_addr star = {.s_addr = 0}; -  source = igmp_find_source_by_addr (group, star); -  if (source) -    igmp_source_forward_stop (source); +	source = igmp_find_source_by_addr(group, star); +	if (source) +		igmp_source_forward_stop(source);  } -static void -igmp_source_forward_reevaluate_one(struct igmp_source *source) +static void igmp_source_forward_reevaluate_one(struct igmp_source *source)  { -  struct prefix_sg sg; -  struct igmp_group *group = source->source_group; -  struct pim_ifchannel *ch; - -  if ((source->source_addr.s_addr != INADDR_ANY) || -      !IGMP_SOURCE_TEST_FORWARDING (source->source_flags)) -    return; - -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = source->source_addr; -  sg.grp = group->group_addr; - -  ch = pim_ifchannel_find (group->group_igmp_sock->interface, &sg); -  if (pim_is_grp_ssm (group->group_addr)) -    { -      /* If SSM group withdraw local membership */ -      if (ch && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) -        { -          if (PIM_DEBUG_PIM_EVENTS) -            zlog_debug ("local membership del for %s as G is now SSM", -                        pim_str_sg_dump (&sg)); -          pim_ifchannel_local_membership_del (group->group_igmp_sock->interface, &sg); -        } -    } -  else -    { -      /* If ASM group add local membership */ -      if (!ch || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) -        { -          if (PIM_DEBUG_PIM_EVENTS) -            zlog_debug ("local membership add for %s as G is now ASM", -                        pim_str_sg_dump (&sg)); -          pim_ifchannel_local_membership_add (group->group_igmp_sock->interface, &sg); -        } -    } +	struct prefix_sg sg; +	struct igmp_group *group = source->source_group; +	struct pim_ifchannel *ch; + +	if ((source->source_addr.s_addr != INADDR_ANY) +	    || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) +		return; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = source->source_addr; +	sg.grp = group->group_addr; + +	ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg); +	if (pim_is_grp_ssm(group->group_addr)) { +		/* If SSM group withdraw local membership */ +		if (ch +		    && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) { +			if (PIM_DEBUG_PIM_EVENTS) +				zlog_debug( +					"local membership del for %s as G is now SSM", +					pim_str_sg_dump(&sg)); +			pim_ifchannel_local_membership_del( +				group->group_igmp_sock->interface, &sg); +		} +	} else { +		/* If ASM group add local membership */ +		if (!ch +		    || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) { +			if (PIM_DEBUG_PIM_EVENTS) +				zlog_debug( +					"local membership add for %s as G is now ASM", +					pim_str_sg_dump(&sg)); +			pim_ifchannel_local_membership_add( +				group->group_igmp_sock->interface, &sg); +		} +	}  } -void -igmp_source_forward_reevaluate_all(void) +void igmp_source_forward_reevaluate_all(void)  { -  struct listnode *ifnode; -  struct interface *ifp; - -  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) -    { -      struct pim_interface *pim_ifp = ifp->info; -      struct listnode  *sock_node; -      struct igmp_sock *igmp; - -      if (!pim_ifp) -        continue; - -      /* scan igmp sockets */ -      for (ALL_LIST_ELEMENTS_RO (pim_ifp->igmp_socket_list, sock_node, igmp)) -        { -          struct listnode *grpnode; -          struct igmp_group *grp; - -          /* scan igmp groups */ -          for (ALL_LIST_ELEMENTS_RO (igmp->igmp_group_list, grpnode, grp)) -            { -              struct listnode    *srcnode; -              struct igmp_source *src; - -              /* scan group sources */ -              for (ALL_LIST_ELEMENTS_RO (grp->group_source_list, -                                        srcnode, src)) -                { -                  igmp_source_forward_reevaluate_one (src); -                } /* scan group sources */ -            } /* scan igmp groups */ -        } /* scan igmp sockets */ -    } /* scan interfaces */ +	struct listnode *ifnode; +	struct interface *ifp; + +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { +		struct pim_interface *pim_ifp = ifp->info; +		struct listnode *sock_node; +		struct igmp_sock *igmp; + +		if (!pim_ifp) +			continue; + +		/* scan igmp sockets */ +		for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, +					  igmp)) { +			struct listnode *grpnode; +			struct igmp_group *grp; + +			/* scan igmp groups */ +			for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, +						  grpnode, grp)) { +				struct listnode *srcnode; +				struct igmp_source *src; + +				/* scan group sources */ +				for (ALL_LIST_ELEMENTS_RO( +					     grp->group_source_list, srcnode, +					     src)) { +					igmp_source_forward_reevaluate_one(src); +				} /* scan group sources */ +			}	 /* scan igmp groups */ +		}		  /* scan igmp sockets */ +	}			  /* scan interfaces */  }  void igmp_source_forward_start(struct igmp_source *source)  { -  struct igmp_group *group; -  struct prefix_sg sg; -  int result; -  int input_iface_vif_index = 0; - -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = source->source_addr; -  sg.grp = source->source_group->group_addr; - -  if (PIM_DEBUG_IGMP_TRACE) { -    zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", -	       __PRETTY_FUNCTION__, - 	       pim_str_sg_dump (&sg), -	       source->source_group->group_igmp_sock->fd, -	       source->source_group->group_igmp_sock->interface->name, -	       IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); -  } - -  /* Prevent IGMP interface from installing multicast route multiple -     times */ -  if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { -    return; -  } - -  group = source->source_group; - -  if (!source->source_channel_oil) { -    struct in_addr vif_source; -    struct pim_interface *pim_oif; -    struct prefix nht_p, src, grp; -    int ret = 0; -    struct pim_nexthop_cache out_pnc; -    struct pim_nexthop nexthop; -    struct pim_upstream *up = NULL; - -    if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp)) -      return; - -    /* Register addr with Zebra NHT */ -    nht_p.family = AF_INET; -    nht_p.prefixlen = IPV4_MAX_BITLEN; -    nht_p.u.prefix4 = vif_source; -    memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); - -    src.family = AF_INET; -    src.prefixlen = IPV4_MAX_BITLEN; -    src.u.prefix4 = vif_source;   //RP or Src address -    grp.family = AF_INET; -    grp.prefixlen = IPV4_MAX_BITLEN; -    grp.u.prefix4 = sg.grp; - -    if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) -      { -        if (out_pnc.nexthop_num) -          { -            up = pim_upstream_find (&sg); -            memset (&nexthop, 0, sizeof (struct pim_nexthop)); -            if (up) -              memcpy (&nexthop, &up->rpf.source_nexthop, sizeof (struct pim_nexthop)); -            //Compute PIM RPF using Cached nexthop -            pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0); -            if (nexthop.interface) -              input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex); -          } -        else -          { -            if (PIM_DEBUG_ZEBRA) -              { -                char buf1[INET_ADDRSTRLEN]; -                char buf2[INET_ADDRSTRLEN]; -                pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1)); -                pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2)); -                zlog_debug ("%s: NHT Nexthop not found for addr %s grp %s" , -                          __PRETTY_FUNCTION__, buf1, buf2); -              } -          } -      } -    else -      input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp); - -    if (PIM_DEBUG_ZEBRA) -      { -        char buf2[INET_ADDRSTRLEN]; -        pim_inet4_dump("<source?>", vif_source, buf2, sizeof(buf2)); -        zlog_debug ("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__, -            pim_str_sg_dump (&sg), buf2, input_iface_vif_index); -      } - -    if (input_iface_vif_index < 1) { -      if (PIM_DEBUG_IGMP_TRACE) -	{ -	  char source_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str)); -	  zlog_debug("%s %s: could not find input interface for source %s", -		     __FILE__, __PRETTY_FUNCTION__, -		     source_str); +	struct igmp_group *group; +	struct prefix_sg sg; +	int result; +	int input_iface_vif_index = 0; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = source->source_addr; +	sg.grp = source->source_group->group_addr; + +	if (PIM_DEBUG_IGMP_TRACE) { +		zlog_debug( +			"%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", +			__PRETTY_FUNCTION__, pim_str_sg_dump(&sg), +			source->source_group->group_igmp_sock->fd, +			source->source_group->group_igmp_sock->interface->name, +			IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); +	} + +	/* Prevent IGMP interface from installing multicast route multiple +	   times */ +	if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { +		return;  	} -      return; -    } - -    /* -      Protect IGMP against adding looped MFC entries created by both -      source and receiver attached to the same interface. See TODO -      T22. -    */ -    pim_oif = source->source_group->group_igmp_sock->interface->info; -    if (!pim_oif) { -      if (PIM_DEBUG_IGMP_TRACE) -	{ -	  zlog_debug("%s: multicast not enabled on oif=%s ?", -		     __PRETTY_FUNCTION__, -		     source->source_group->group_igmp_sock->interface->name); + +	group = source->source_group; + +	if (!source->source_channel_oil) { +		struct in_addr vif_source; +		struct pim_interface *pim_oif; +		struct prefix nht_p, src, grp; +		int ret = 0; +		struct pim_nexthop_cache out_pnc; +		struct pim_nexthop nexthop; +		struct pim_upstream *up = NULL; + +		if (!pim_rp_set_upstream_addr(&vif_source, source->source_addr, +					      sg.grp)) +			return; + +		/* Register addr with Zebra NHT */ +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4 = vif_source; +		memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + +		src.family = AF_INET; +		src.prefixlen = IPV4_MAX_BITLEN; +		src.u.prefix4 = vif_source; // RP or Src address +		grp.family = AF_INET; +		grp.prefixlen = IPV4_MAX_BITLEN; +		grp.u.prefix4 = sg.grp; + +		if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL, +						     &out_pnc)) +		    == 1) { +			if (out_pnc.nexthop_num) { +				up = pim_upstream_find(&sg); +				memset(&nexthop, 0, sizeof(struct pim_nexthop)); +				if (up) +					memcpy(&nexthop, +					       &up->rpf.source_nexthop, +					       sizeof(struct pim_nexthop)); +				// Compute PIM RPF using Cached nexthop +				pim_ecmp_nexthop_search(&out_pnc, &nexthop, +							&src, &grp, 0); +				if (nexthop.interface) +					input_iface_vif_index = +						pim_if_find_vifindex_by_ifindex( +							nexthop.interface->ifindex); +			} else { +				if (PIM_DEBUG_ZEBRA) { +					char buf1[INET_ADDRSTRLEN]; +					char buf2[INET_ADDRSTRLEN]; +					pim_inet4_dump("<source?>", +						       nht_p.u.prefix4, buf1, +						       sizeof(buf1)); +					pim_inet4_dump("<source?>", +						       grp.u.prefix4, buf2, +						       sizeof(buf2)); +					zlog_debug( +						"%s: NHT Nexthop not found for addr %s grp %s", +						__PRETTY_FUNCTION__, buf1, +						buf2); +				} +			} +		} else +			input_iface_vif_index = +				pim_ecmp_fib_lookup_if_vif_index(vif_source, +								 &src, &grp); + +		if (PIM_DEBUG_ZEBRA) { +			char buf2[INET_ADDRSTRLEN]; +			pim_inet4_dump("<source?>", vif_source, buf2, +				       sizeof(buf2)); +			zlog_debug("%s: NHT %s vif_source %s vif_index:%d ", +				   __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), +				   buf2, input_iface_vif_index); +		} + +		if (input_iface_vif_index < 1) { +			if (PIM_DEBUG_IGMP_TRACE) { +				char source_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<source?>", source->source_addr, +					       source_str, sizeof(source_str)); +				zlog_debug( +					"%s %s: could not find input interface for source %s", +					__FILE__, __PRETTY_FUNCTION__, +					source_str); +			} +			return; +		} + +		/* +		  Protect IGMP against adding looped MFC entries created by both +		  source and receiver attached to the same interface. See TODO +		  T22. +		*/ +		pim_oif = +			source->source_group->group_igmp_sock->interface->info; +		if (!pim_oif) { +			if (PIM_DEBUG_IGMP_TRACE) { +				zlog_debug( +					"%s: multicast not enabled on oif=%s ?", +					__PRETTY_FUNCTION__, +					source->source_group->group_igmp_sock +						->interface->name); +			} +			return; +		} + +		if (input_iface_vif_index == pim_oif->mroute_vif_index) { +			/* ignore request for looped MFC entry */ +			if (PIM_DEBUG_IGMP_TRACE) { +				zlog_debug( +					"%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", +					__PRETTY_FUNCTION__, +					pim_str_sg_dump(&sg), +					source->source_group->group_igmp_sock +						->fd, +					source->source_group->group_igmp_sock +						->interface->name, +					input_iface_vif_index); +			} +			return; +		} + +		source->source_channel_oil = +			pim_channel_oil_add(&sg, input_iface_vif_index); +		if (!source->source_channel_oil) { +			if (PIM_DEBUG_IGMP_TRACE) { +				zlog_debug( +					"%s %s: could not create OIL for channel (S,G)=%s", +					__FILE__, __PRETTY_FUNCTION__, +					pim_str_sg_dump(&sg)); +			} +			return; +		}  	} -      return; -    } - -    if (input_iface_vif_index == pim_oif->mroute_vif_index) { -      /* ignore request for looped MFC entry */ -      if (PIM_DEBUG_IGMP_TRACE) { -	zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", -		   __PRETTY_FUNCTION__, -		   pim_str_sg_dump (&sg), -		   source->source_group->group_igmp_sock->fd, -		   source->source_group->group_igmp_sock->interface->name, -		   input_iface_vif_index); -      } -      return; -    } - -    source->source_channel_oil = pim_channel_oil_add(&sg, -						     input_iface_vif_index); -    if (!source->source_channel_oil) { -      if (PIM_DEBUG_IGMP_TRACE) -	{ -	  zlog_debug("%s %s: could not create OIL for channel (S,G)=%s", -		    __FILE__, __PRETTY_FUNCTION__, -		    pim_str_sg_dump (&sg)); + +	result = pim_channel_add_oif(source->source_channel_oil, +				     group->group_igmp_sock->interface, +				     PIM_OIF_FLAG_PROTO_IGMP); +	if (result) { +		if (PIM_DEBUG_MROUTE) { +			zlog_warn("%s: add_oif() failed with return=%d", +				  __func__, result); +		} +		return;  	} -      return; -    } -  } - -  result = pim_channel_add_oif(source->source_channel_oil, -			       group->group_igmp_sock->interface, -			       PIM_OIF_FLAG_PROTO_IGMP); -  if (result) { -    if (PIM_DEBUG_MROUTE) -      { -        zlog_warn("%s: add_oif() failed with return=%d", -                  __func__, result); -      } -    return; -  } - -  /* -    Feed IGMPv3-gathered local membership information into PIM -    per-interface (S,G) state. -   */ -  if (!pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg)) -    { -      if (PIM_DEBUG_MROUTE) -	zlog_warn ("%s: Failure to add local membership for %s", -		   __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); -      return; -    } - -  IGMP_SOURCE_DO_FORWARDING(source->source_flags); + +	/* +	  Feed IGMPv3-gathered local membership information into PIM +	  per-interface (S,G) state. +	 */ +	if (!pim_ifchannel_local_membership_add( +		    group->group_igmp_sock->interface, &sg)) { +		if (PIM_DEBUG_MROUTE) +			zlog_warn("%s: Failure to add local membership for %s", +				  __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); +		return; +	} + +	IGMP_SOURCE_DO_FORWARDING(source->source_flags);  }  /* @@ -966,203 +1010,219 @@ void igmp_source_forward_start(struct igmp_source *source)   */  void igmp_source_forward_stop(struct igmp_source *source)  { -  struct igmp_group *group; -  struct prefix_sg sg; -  int result; - -  memset (&sg, 0, sizeof (struct prefix_sg)); -  sg.src = source->source_addr; -  sg.grp = source->source_group->group_addr; - -  if (PIM_DEBUG_IGMP_TRACE) { -    zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", -	       __PRETTY_FUNCTION__, -	       pim_str_sg_dump (&sg), -	       source->source_group->group_igmp_sock->fd, -	       source->source_group->group_igmp_sock->interface->name, -	       IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); -  } - -  /* Prevent IGMP interface from removing multicast route multiple -     times */ -  if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { -    return; -  } - -  group = source->source_group; - -  /* -   It appears that in certain circumstances that  -   igmp_source_forward_stop is called when IGMP forwarding -   was not enabled in oif_flags for this outgoing interface. -   Possibly because of multiple calls. When that happens, we -   enter the below if statement and this function returns early -   which in turn triggers the calling function to assert. -   Making the call to pim_channel_del_oif and ignoring the return code -   fixes the issue without ill effect, similar to -   pim_forward_stop below. -  */ -  result = pim_channel_del_oif(source->source_channel_oil, -                               group->group_igmp_sock->interface, -                               PIM_OIF_FLAG_PROTO_IGMP); -  if (result) { -    if (PIM_DEBUG_IGMP_TRACE) -      zlog_debug("%s: pim_channel_del_oif() failed with return=%d", -		 __func__, result); -    return; -  } - -  /* -    Feed IGMPv3-gathered local membership information into PIM -    per-interface (S,G) state. -   */ -  pim_ifchannel_local_membership_del(group->group_igmp_sock->interface, -				     &sg); - -  IGMP_SOURCE_DONT_FORWARDING(source->source_flags); +	struct igmp_group *group; +	struct prefix_sg sg; +	int result; + +	memset(&sg, 0, sizeof(struct prefix_sg)); +	sg.src = source->source_addr; +	sg.grp = source->source_group->group_addr; + +	if (PIM_DEBUG_IGMP_TRACE) { +		zlog_debug( +			"%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", +			__PRETTY_FUNCTION__, pim_str_sg_dump(&sg), +			source->source_group->group_igmp_sock->fd, +			source->source_group->group_igmp_sock->interface->name, +			IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); +	} + +	/* Prevent IGMP interface from removing multicast route multiple +	   times */ +	if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { +		return; +	} + +	group = source->source_group; + +	/* +	 It appears that in certain circumstances that +	 igmp_source_forward_stop is called when IGMP forwarding +	 was not enabled in oif_flags for this outgoing interface. +	 Possibly because of multiple calls. When that happens, we +	 enter the below if statement and this function returns early +	 which in turn triggers the calling function to assert. +	 Making the call to pim_channel_del_oif and ignoring the return code +	 fixes the issue without ill effect, similar to +	 pim_forward_stop below. +	*/ +	result = pim_channel_del_oif(source->source_channel_oil, +				     group->group_igmp_sock->interface, +				     PIM_OIF_FLAG_PROTO_IGMP); +	if (result) { +		if (PIM_DEBUG_IGMP_TRACE) +			zlog_debug( +				"%s: pim_channel_del_oif() failed with return=%d", +				__func__, result); +		return; +	} + +	/* +	  Feed IGMPv3-gathered local membership information into PIM +	  per-interface (S,G) state. +	 */ +	pim_ifchannel_local_membership_del(group->group_igmp_sock->interface, +					   &sg); + +	IGMP_SOURCE_DONT_FORWARDING(source->source_flags);  }  void pim_forward_start(struct pim_ifchannel *ch)  { -  struct pim_upstream *up = ch->upstream; -  uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; -  int input_iface_vif_index =  0; - -  if (PIM_DEBUG_PIM_TRACE) { -    char source_str[INET_ADDRSTRLEN]; -    char group_str[INET_ADDRSTRLEN]; -    char upstream_str[INET_ADDRSTRLEN]; - -    pim_inet4_dump("<source?>", ch->sg.src, source_str, sizeof(source_str)); -    pim_inet4_dump("<group?>", ch->sg.grp, group_str, sizeof(group_str)); -    pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, sizeof(upstream_str)); -    zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", -	       __PRETTY_FUNCTION__, -	       source_str, group_str, ch->interface->name, upstream_str); -  } - -  /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, -     as part of mroute_del called by pim_forward_stop. -  */ -  if (!up->channel_oil || -      (up->channel_oil && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) -    { -      struct prefix nht_p, src, grp; -      int ret = 0; -      struct pim_nexthop_cache out_pnc; - -      /* Register addr with Zebra NHT */ -      nht_p.family = AF_INET; -      nht_p.prefixlen = IPV4_MAX_BITLEN; -      nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; -      grp.family = AF_INET; -      grp.prefixlen = IPV4_MAX_BITLEN; -      grp.u.prefix4 = up->sg.grp; -      memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); - -      if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) -        { -          if (out_pnc.nexthop_num) -            { -              src.family = AF_INET; -              src.prefixlen = IPV4_MAX_BITLEN; -              src.u.prefix4 = up->upstream_addr; //RP or Src address -              grp.family = AF_INET; -              grp.prefixlen = IPV4_MAX_BITLEN; -              grp.u.prefix4 = up->sg.grp; -              //Compute PIM RPF using Cached nexthop -              if (pim_ecmp_nexthop_search (&out_pnc, &up->rpf.source_nexthop, &src, &grp, 0) == 0) -                input_iface_vif_index = pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.interface->ifindex); -              else -                { -                  if (PIM_DEBUG_TRACE) -                    zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__, up->sg_str); -                } -            } -          else -            { -              if (PIM_DEBUG_ZEBRA) -                { -                  char buf1[INET_ADDRSTRLEN]; -                  char buf2[INET_ADDRSTRLEN]; -                  pim_inet4_dump("<source?>", nht_p.u.prefix4, buf1, sizeof(buf1)); -                  pim_inet4_dump("<source?>", grp.u.prefix4, buf2, sizeof(buf2)); -                  zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" , -                          __PRETTY_FUNCTION__, buf1, buf2); -                } -            } -        } -      else -        input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(up->upstream_addr, &src, &grp); - -      if (input_iface_vif_index < 1) -        { -          if (PIM_DEBUG_PIM_TRACE) -            { -              char source_str[INET_ADDRSTRLEN]; -              pim_inet4_dump("<source?>", up->sg.src, source_str, sizeof(source_str)); -              zlog_debug("%s %s: could not find input interface for source %s", -                      __FILE__, __PRETTY_FUNCTION__, -                      source_str); -            } -          return; -        } -      if (PIM_DEBUG_TRACE) -        { -          struct interface *in_intf = pim_if_find_by_vif_index (input_iface_vif_index); -          zlog_debug ("%s: Update channel_oil IIF %s VIFI %d entry %s ", -                      __PRETTY_FUNCTION__, in_intf ? in_intf->name : "NIL", -                      input_iface_vif_index, up->sg_str); -        } -      up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index); -      if (!up->channel_oil) -        { -          if (PIM_DEBUG_PIM_TRACE) -            zlog_debug ("%s %s: could not create OIL for channel (S,G)=%s", -                        __FILE__, __PRETTY_FUNCTION__, up->sg_str); -          return; -        } -    } - -  if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) -    mask = PIM_OIF_FLAG_PROTO_IGMP; - -  pim_channel_add_oif (up->channel_oil, ch->interface, mask); +	struct pim_upstream *up = ch->upstream; +	uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; +	int input_iface_vif_index = 0; + +	if (PIM_DEBUG_PIM_TRACE) { +		char source_str[INET_ADDRSTRLEN]; +		char group_str[INET_ADDRSTRLEN]; +		char upstream_str[INET_ADDRSTRLEN]; + +		pim_inet4_dump("<source?>", ch->sg.src, source_str, +			       sizeof(source_str)); +		pim_inet4_dump("<group?>", ch->sg.grp, group_str, +			       sizeof(group_str)); +		pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, +			       sizeof(upstream_str)); +		zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__, +			   source_str, group_str, ch->interface->name, +			   upstream_str); +	} + +	/* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, +	   as part of mroute_del called by pim_forward_stop. +	*/ +	if (!up->channel_oil +	    || (up->channel_oil +		&& up->channel_oil->oil.mfcc_parent >= MAXVIFS)) { +		struct prefix nht_p, src, grp; +		int ret = 0; +		struct pim_nexthop_cache out_pnc; + +		/* Register addr with Zebra NHT */ +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; +		grp.family = AF_INET; +		grp.prefixlen = IPV4_MAX_BITLEN; +		grp.u.prefix4 = up->sg.grp; +		memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + +		if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL, +						     &out_pnc)) +		    == 1) { +			if (out_pnc.nexthop_num) { +				src.family = AF_INET; +				src.prefixlen = IPV4_MAX_BITLEN; +				src.u.prefix4 = +					up->upstream_addr; // RP or Src address +				grp.family = AF_INET; +				grp.prefixlen = IPV4_MAX_BITLEN; +				grp.u.prefix4 = up->sg.grp; +				// Compute PIM RPF using Cached nexthop +				if (pim_ecmp_nexthop_search( +					    &out_pnc, &up->rpf.source_nexthop, +					    &src, &grp, 0) +				    == 0) +					input_iface_vif_index = +						pim_if_find_vifindex_by_ifindex( +							up->rpf.source_nexthop +								.interface->ifindex); +				else { +					if (PIM_DEBUG_TRACE) +						zlog_debug( +							"%s: Nexthop selection failed for %s ", +							__PRETTY_FUNCTION__, +							up->sg_str); +				} +			} else { +				if (PIM_DEBUG_ZEBRA) { +					char buf1[INET_ADDRSTRLEN]; +					char buf2[INET_ADDRSTRLEN]; +					pim_inet4_dump("<source?>", +						       nht_p.u.prefix4, buf1, +						       sizeof(buf1)); +					pim_inet4_dump("<source?>", +						       grp.u.prefix4, buf2, +						       sizeof(buf2)); +					zlog_debug( +						"%s: NHT pnc is NULL for addr %s grp %s", +						__PRETTY_FUNCTION__, buf1, +						buf2); +				} +			} +		} else +			input_iface_vif_index = +				pim_ecmp_fib_lookup_if_vif_index( +					up->upstream_addr, &src, &grp); + +		if (input_iface_vif_index < 1) { +			if (PIM_DEBUG_PIM_TRACE) { +				char source_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<source?>", up->sg.src, +					       source_str, sizeof(source_str)); +				zlog_debug( +					"%s %s: could not find input interface for source %s", +					__FILE__, __PRETTY_FUNCTION__, +					source_str); +			} +			return; +		} +		if (PIM_DEBUG_TRACE) { +			struct interface *in_intf = +				pim_if_find_by_vif_index(input_iface_vif_index); +			zlog_debug( +				"%s: Update channel_oil IIF %s VIFI %d entry %s ", +				__PRETTY_FUNCTION__, +				in_intf ? in_intf->name : "NIL", +				input_iface_vif_index, up->sg_str); +		} +		up->channel_oil = +			pim_channel_oil_add(&up->sg, input_iface_vif_index); +		if (!up->channel_oil) { +			if (PIM_DEBUG_PIM_TRACE) +				zlog_debug( +					"%s %s: could not create OIL for channel (S,G)=%s", +					__FILE__, __PRETTY_FUNCTION__, +					up->sg_str); +			return; +		} +	} + +	if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) +		mask = PIM_OIF_FLAG_PROTO_IGMP; + +	pim_channel_add_oif(up->channel_oil, ch->interface, mask);  }  void pim_forward_stop(struct pim_ifchannel *ch)  { -  struct pim_upstream *up = ch->upstream; +	struct pim_upstream *up = ch->upstream; -  if (PIM_DEBUG_PIM_TRACE) { -    zlog_debug("%s: (S,G)=%s oif=%s", -	       __PRETTY_FUNCTION__, -	       ch->sg_str, ch->interface->name); -  } +	if (PIM_DEBUG_PIM_TRACE) { +		zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__, +			   ch->sg_str, ch->interface->name); +	} -  pim_channel_del_oif(up->channel_oil, -                      ch->interface, -                      PIM_OIF_FLAG_PROTO_PIM); +	pim_channel_del_oif(up->channel_oil, ch->interface, +			    PIM_OIF_FLAG_PROTO_PIM);  } -void -pim_zebra_zclient_update (struct vty *vty) +void pim_zebra_zclient_update(struct vty *vty)  { -  vty_out(vty, "Zclient update socket: "); - -  if (zclient) { -    vty_out (vty, "%d failures=%d\n", zclient->sock, -	    zclient->fail); -  } -  else { -    vty_out (vty, "<null zclient>\n"); -  } +	vty_out(vty, "Zclient update socket: "); + +	if (zclient) { +		vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail); +	} else { +		vty_out(vty, "<null zclient>\n"); +	}  } -struct zclient *pim_zebra_zclient_get (void) +struct zclient *pim_zebra_zclient_get(void)  { -  if (zclient) -    return zclient; -  else -    return NULL; +	if (zclient) +		return zclient; +	else +		return NULL;  } diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index 37024073ea..9b5450d66a 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -27,9 +27,9 @@  #include "pim_ifchannel.h"  void pim_zebra_init(void); -void pim_zebra_zclient_update (struct vty *vty); +void pim_zebra_zclient_update(struct vty *vty); -void pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index); +void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index);  void pim_scan_oil(void);  void igmp_anysource_forward_start(struct igmp_group *group); @@ -43,5 +43,5 @@ void pim_forward_start(struct pim_ifchannel *ch);  void pim_forward_stop(struct pim_ifchannel *ch);  void sched_rpf_cache_refresh(void); -struct zclient *pim_zebra_zclient_get (void); +struct zclient *pim_zebra_zclient_get(void);  #endif /* PIM_ZEBRA_H */ diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f405a39c9d..027b18e123 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -43,491 +43,504 @@ static void zclient_lookup_sched(struct zclient *zlookup, int delay);  /* Connect to zebra for nexthop lookup. */  static int zclient_lookup_connect(struct thread *t)  { -  struct zclient *zlookup; - -  zlookup = THREAD_ARG(t); - -  if (zlookup->sock >= 0) { -    return 0; -  } - -  if (zclient_socket_connect(zlookup) < 0) { -    ++zlookup->fail; -    zlog_warn("%s: failure connecting zclient socket: failures=%d", -	      __PRETTY_FUNCTION__, zlookup->fail); -  } -  else { -    zlookup->fail = 0; /* reset counter on connection */ -  } - -  if (zlookup->sock < 0) { -    /* Since last connect failed, retry within 10 secs */ -    zclient_lookup_sched(zlookup, 10); -    return -1; -  } - -  return 0; +	struct zclient *zlookup; + +	zlookup = THREAD_ARG(t); + +	if (zlookup->sock >= 0) { +		return 0; +	} + +	if (zclient_socket_connect(zlookup) < 0) { +		++zlookup->fail; +		zlog_warn("%s: failure connecting zclient socket: failures=%d", +			  __PRETTY_FUNCTION__, zlookup->fail); +	} else { +		zlookup->fail = 0; /* reset counter on connection */ +	} + +	if (zlookup->sock < 0) { +		/* Since last connect failed, retry within 10 secs */ +		zclient_lookup_sched(zlookup, 10); +		return -1; +	} + +	return 0;  }  /* Schedule connection with delay. */  static void zclient_lookup_sched(struct zclient *zlookup, int delay)  { -  thread_add_timer(master, zclient_lookup_connect, zlookup, delay, -                   &zlookup->t_connect); +	thread_add_timer(master, zclient_lookup_connect, zlookup, delay, +			 &zlookup->t_connect); -  zlog_notice("%s: zclient lookup connection scheduled for %d seconds", -	      __PRETTY_FUNCTION__, delay); +	zlog_notice("%s: zclient lookup connection scheduled for %d seconds", +		    __PRETTY_FUNCTION__, delay);  }  /* Schedule connection for now. */  static void zclient_lookup_sched_now(struct zclient *zlookup)  { -  thread_add_event(master, zclient_lookup_connect, zlookup, 0, -                   &zlookup->t_connect); +	thread_add_event(master, zclient_lookup_connect, zlookup, 0, +			 &zlookup->t_connect); -  zlog_notice("%s: zclient lookup immediate connection scheduled", -	      __PRETTY_FUNCTION__); +	zlog_notice("%s: zclient lookup immediate connection scheduled", +		    __PRETTY_FUNCTION__);  }  /* Schedule reconnection, if needed. */  static void zclient_lookup_reconnect(struct zclient *zlookup)  { -  if (zlookup->t_connect) { -    return; -  } +	if (zlookup->t_connect) { +		return; +	} -  zclient_lookup_sched_now(zlookup); +	zclient_lookup_sched_now(zlookup);  }  static void zclient_lookup_failed(struct zclient *zlookup)  { -  if (zlookup->sock >= 0) { -    if (close(zlookup->sock)) { -      zlog_warn("%s: closing fd=%d: errno=%d %s", __func__, zlookup->sock, -		errno, safe_strerror(errno)); -    } -    zlookup->sock = -1; -  } - -  zclient_lookup_reconnect(zlookup); +	if (zlookup->sock >= 0) { +		if (close(zlookup->sock)) { +			zlog_warn("%s: closing fd=%d: errno=%d %s", __func__, +				  zlookup->sock, errno, safe_strerror(errno)); +		} +		zlookup->sock = -1; +	} + +	zclient_lookup_reconnect(zlookup);  } -void -zclient_lookup_free (void) +void zclient_lookup_free(void)  { -  zclient_stop (zlookup); -  zclient_free (zlookup); -  zlookup = NULL; +	zclient_stop(zlookup); +	zclient_free(zlookup); +	zlookup = NULL;  } -void -zclient_lookup_new (void) +void zclient_lookup_new(void)  { -  zlookup = zclient_new (master); -  if (!zlookup) { -    zlog_err("%s: zclient_new() failure", -	     __PRETTY_FUNCTION__); -    return; -  } - -  zlookup->sock = -1; -  zlookup->t_connect = NULL; +	zlookup = zclient_new(master); +	if (!zlookup) { +		zlog_err("%s: zclient_new() failure", __PRETTY_FUNCTION__); +		return; +	} -  zclient_lookup_sched_now(zlookup); +	zlookup->sock = -1; +	zlookup->t_connect = NULL; -  zlog_notice("%s: zclient lookup socket initialized", -	      __PRETTY_FUNCTION__); +	zclient_lookup_sched_now(zlookup); +	zlog_notice("%s: zclient lookup socket initialized", +		    __PRETTY_FUNCTION__);  }  static int zclient_read_nexthop(struct zclient *zlookup,  				struct pim_zlookup_nexthop nexthop_tab[], -				const int tab_size, -				struct in_addr addr) +				const int tab_size, struct in_addr addr)  { -  int num_ifindex = 0; -  struct stream *s; -  const uint16_t MIN_LEN = 10; /* getipv4=4 getc=1 getl=4 getc=1 */ -  uint16_t length; -  u_char marker; -  u_char version; -  vrf_id_t vrf_id; -  uint16_t command = 0; -  struct in_addr raddr; -  uint8_t distance; -  uint32_t metric; -  int nexthop_num; -  int i, err; - -  if (PIM_DEBUG_PIM_TRACE_DETAIL) { -    char addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -    zlog_debug("%s: addr=%s",  -	       __PRETTY_FUNCTION__, -	       addr_str); -  } - -  s = zlookup->ibuf; - -  while (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) -    { -      stream_reset(s); -      err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, -				 &vrf_id, &command); -      if (err < 0) { -	zlog_err("%s %s: zclient_read_header() failed", -		 __FILE__, __PRETTY_FUNCTION__); -	zclient_lookup_failed(zlookup); -	return -1; -      } - -      if (length < MIN_LEN) { -	zlog_err("%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d", -		 __FILE__, __PRETTY_FUNCTION__, length, MIN_LEN); -	zclient_lookup_failed(zlookup); -	return -2; -      } -    } - -  raddr.s_addr = stream_get_ipv4(s); - -  if (raddr.s_addr != addr.s_addr) { -    char addr_str[INET_ADDRSTRLEN]; -    char raddr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -    pim_inet4_dump("<raddr?>", raddr, raddr_str, sizeof(raddr_str)); -    zlog_warn("%s: address mismatch: addr=%s raddr=%s",  -	       __PRETTY_FUNCTION__, -	       addr_str, raddr_str); -    /* warning only */ -  } - -  distance = stream_getc(s); -  metric = stream_getl(s); -  nexthop_num = stream_getc(s); - -  if (nexthop_num < 1) { -    zlog_err("%s: socket %d bad nexthop_num=%d", -            __func__, zlookup->sock, nexthop_num); -    return -6; -  } - -  for (i = 0; i < nexthop_num; ++i) { -    enum nexthop_types_t nexthop_type; -    struct pim_neighbor *nbr; -    struct prefix p; - -    nexthop_type = stream_getc(s); -    if (num_ifindex >= tab_size) { -      char addr_str[INET_ADDRSTRLEN]; -      pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -      zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s", -		__FILE__, __PRETTY_FUNCTION__, -		(num_ifindex + 1), tab_size, addr_str); -      return num_ifindex; -    } -    switch (nexthop_type) { -    case NEXTHOP_TYPE_IFINDEX: -    case NEXTHOP_TYPE_IPV4_IFINDEX: -    case NEXTHOP_TYPE_IPV4: -      nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; -      if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX || -	  nexthop_type == NEXTHOP_TYPE_IPV4) { -	nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); -      } -      else { -	nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; -      } -      nexthop_tab[num_ifindex].ifindex           = stream_getl(s); -      nexthop_tab[num_ifindex].protocol_distance = distance; -      nexthop_tab[num_ifindex].route_metric      = metric; -      ++num_ifindex; -      break; -    case NEXTHOP_TYPE_IPV6_IFINDEX: -      nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; -      stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, -		  s, -		  sizeof(struct in6_addr)); -      nexthop_tab[num_ifindex].ifindex = stream_getl (s); - -      p.family = AF_INET6; -      p.prefixlen = IPV6_MAX_PREFIXLEN; -      memcpy (&p.u.prefix6, -	      &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, -	      sizeof(struct in6_addr)); - -      /* -       * If we are sending v6 secondary assume we receive v6 secondary -       */ -      if (pimg->send_v6_secondary) -        nbr = pim_neighbor_find_by_secondary(if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT), &p); -      else -        nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); -      if (nbr) -        { -          nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; -          nexthop_tab[num_ifindex].nexthop_addr.u.prefix4 = nbr->source_addr; -        } -        ++num_ifindex; -      break; -    default: -      /* do nothing */ -      { -	char addr_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -	zlog_warn("%s %s: found non-ifindex nexthop type=%d for address %s", -		 __FILE__, __PRETTY_FUNCTION__, -		  nexthop_type, addr_str); -      } -      break; -    } -  } - -  return num_ifindex; +	int num_ifindex = 0; +	struct stream *s; +	const uint16_t MIN_LEN = 10; /* getipv4=4 getc=1 getl=4 getc=1 */ +	uint16_t length; +	u_char marker; +	u_char version; +	vrf_id_t vrf_id; +	uint16_t command = 0; +	struct in_addr raddr; +	uint8_t distance; +	uint32_t metric; +	int nexthop_num; +	int i, err; + +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str); +	} + +	s = zlookup->ibuf; + +	while (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) { +		stream_reset(s); +		err = zclient_read_header(s, zlookup->sock, &length, &marker, +					  &version, &vrf_id, &command); +		if (err < 0) { +			zlog_err("%s %s: zclient_read_header() failed", +				 __FILE__, __PRETTY_FUNCTION__); +			zclient_lookup_failed(zlookup); +			return -1; +		} + +		if (length < MIN_LEN) { +			zlog_err( +				"%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d", +				__FILE__, __PRETTY_FUNCTION__, length, MIN_LEN); +			zclient_lookup_failed(zlookup); +			return -2; +		} +	} + +	raddr.s_addr = stream_get_ipv4(s); + +	if (raddr.s_addr != addr.s_addr) { +		char addr_str[INET_ADDRSTRLEN]; +		char raddr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		pim_inet4_dump("<raddr?>", raddr, raddr_str, sizeof(raddr_str)); +		zlog_warn("%s: address mismatch: addr=%s raddr=%s", +			  __PRETTY_FUNCTION__, addr_str, raddr_str); +		/* warning only */ +	} + +	distance = stream_getc(s); +	metric = stream_getl(s); +	nexthop_num = stream_getc(s); + +	if (nexthop_num < 1) { +		zlog_err("%s: socket %d bad nexthop_num=%d", __func__, +			 zlookup->sock, nexthop_num); +		return -6; +	} + +	for (i = 0; i < nexthop_num; ++i) { +		enum nexthop_types_t nexthop_type; +		struct pim_neighbor *nbr; +		struct prefix p; + +		nexthop_type = stream_getc(s); +		if (num_ifindex >= tab_size) { +			char addr_str[INET_ADDRSTRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			zlog_warn( +				"%s %s: found too many nexthop ifindexes (%d > %d) for address %s", +				__FILE__, __PRETTY_FUNCTION__, +				(num_ifindex + 1), tab_size, addr_str); +			return num_ifindex; +		} +		switch (nexthop_type) { +		case NEXTHOP_TYPE_IFINDEX: +		case NEXTHOP_TYPE_IPV4_IFINDEX: +		case NEXTHOP_TYPE_IPV4: +			nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; +			if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX +			    || nexthop_type == NEXTHOP_TYPE_IPV4) { +				nexthop_tab[num_ifindex] +					.nexthop_addr.u.prefix4.s_addr = +					stream_get_ipv4(s); +			} else { +				nexthop_tab[num_ifindex] +					.nexthop_addr.u.prefix4.s_addr = +					PIM_NET_INADDR_ANY; +			} +			nexthop_tab[num_ifindex].ifindex = stream_getl(s); +			nexthop_tab[num_ifindex].protocol_distance = distance; +			nexthop_tab[num_ifindex].route_metric = metric; +			++num_ifindex; +			break; +		case NEXTHOP_TYPE_IPV6_IFINDEX: +			nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; +			stream_get(&nexthop_tab[num_ifindex] +					    .nexthop_addr.u.prefix6, +				   s, sizeof(struct in6_addr)); +			nexthop_tab[num_ifindex].ifindex = stream_getl(s); + +			p.family = AF_INET6; +			p.prefixlen = IPV6_MAX_PREFIXLEN; +			memcpy(&p.u.prefix6, +			       &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, +			       sizeof(struct in6_addr)); + +			/* +			 * If we are sending v6 secondary assume we receive v6 +			 * secondary +			 */ +			if (pimg->send_v6_secondary) +				nbr = pim_neighbor_find_by_secondary( +					if_lookup_by_index( +						nexthop_tab[num_ifindex] +							.ifindex, +						VRF_DEFAULT), +					&p); +			else +				nbr = pim_neighbor_find_if(if_lookup_by_index( +					nexthop_tab[num_ifindex].ifindex, +					VRF_DEFAULT)); +			if (nbr) { +				nexthop_tab[num_ifindex].nexthop_addr.family = +					AF_INET; +				nexthop_tab[num_ifindex] +					.nexthop_addr.u.prefix4 = +					nbr->source_addr; +			} +			++num_ifindex; +			break; +		default: +			/* do nothing */ +			{ +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_warn( +					"%s %s: found non-ifindex nexthop type=%d for address %s", +					__FILE__, __PRETTY_FUNCTION__, +					nexthop_type, addr_str); +			} +			break; +		} +	} + +	return num_ifindex;  } -static int -zclient_lookup_nexthop_once (struct pim_zlookup_nexthop nexthop_tab[], -			     const int tab_size, -			     struct in_addr addr) +static int zclient_lookup_nexthop_once(struct pim_zlookup_nexthop nexthop_tab[], +				       const int tab_size, struct in_addr addr)  { -  struct stream *s; -  int ret; - -  if (PIM_DEBUG_PIM_TRACE_DETAIL) { -    char addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -    zlog_debug("%s: addr=%s",  -	       __PRETTY_FUNCTION__, -	       addr_str); -  } - -  /* Check socket. */ -  if (zlookup->sock < 0) { -    zlog_err("%s %s: zclient lookup socket is not connected", -	     __FILE__, __PRETTY_FUNCTION__); -    zclient_lookup_failed(zlookup); -    return -1; -  } -   -  s = zlookup->obuf; -  stream_reset(s); -  zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, VRF_DEFAULT); -  stream_put_in_addr(s, &addr); -  stream_putw_at(s, 0, stream_get_endp(s)); -   -  ret = writen(zlookup->sock, s->data, stream_get_endp(s)); -  if (ret < 0) { -    zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", -	     __FILE__, __PRETTY_FUNCTION__, errno); -    zclient_lookup_failed(zlookup); -    return -2; -  } -  if (ret == 0) { -    zlog_err("%s %s: connection closed on zclient lookup socket", -	     __FILE__, __PRETTY_FUNCTION__); -    zclient_lookup_failed(zlookup); -    return -3; -  } -   -  return zclient_read_nexthop(zlookup, nexthop_tab, -			      tab_size, addr); +	struct stream *s; +	int ret; + +	if (PIM_DEBUG_PIM_TRACE_DETAIL) { +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str); +	} + +	/* Check socket. */ +	if (zlookup->sock < 0) { +		zlog_err("%s %s: zclient lookup socket is not connected", +			 __FILE__, __PRETTY_FUNCTION__); +		zclient_lookup_failed(zlookup); +		return -1; +	} + +	s = zlookup->obuf; +	stream_reset(s); +	zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, VRF_DEFAULT); +	stream_put_in_addr(s, &addr); +	stream_putw_at(s, 0, stream_get_endp(s)); + +	ret = writen(zlookup->sock, s->data, stream_get_endp(s)); +	if (ret < 0) { +		zlog_err( +			"%s %s: writen() failure: %d writing to zclient lookup socket", +			__FILE__, __PRETTY_FUNCTION__, errno); +		zclient_lookup_failed(zlookup); +		return -2; +	} +	if (ret == 0) { +		zlog_err("%s %s: connection closed on zclient lookup socket", +			 __FILE__, __PRETTY_FUNCTION__); +		zclient_lookup_failed(zlookup); +		return -3; +	} + +	return zclient_read_nexthop(zlookup, nexthop_tab, tab_size, addr);  } -int -zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], -			const int tab_size, -			struct in_addr addr, -			int max_lookup) +int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], +			   const int tab_size, struct in_addr addr, +			   int max_lookup)  { -  int lookup; -  uint32_t route_metric = 0xFFFFFFFF; -  uint8_t  protocol_distance = 0xFF; - -  qpim_nexthop_lookups++; - -  for (lookup = 0; lookup < max_lookup; ++lookup) { -    int num_ifindex; -    int first_ifindex; -    struct prefix nexthop_addr; - -    num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, -					      tab_size, addr); -    if (num_ifindex < 1) { -      if (PIM_DEBUG_ZEBRA) { -	char addr_str[INET_ADDRSTRLEN]; -	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -	zlog_debug("%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s", -		   __FILE__, __PRETTY_FUNCTION__, -		   lookup, max_lookup, addr_str); -      } -      return -1; -    } - -    if (lookup < 1) { -      /* this is the non-recursive lookup - save original metric/distance */ -      route_metric = nexthop_tab[0].route_metric; -      protocol_distance = nexthop_tab[0].protocol_distance; -    } -     -    /* -     * FIXME: Non-recursive nexthop ensured only for first ifindex. -     * However, recursive route lookup should really be fixed in zebra daemon. -     * See also TODO T24. -     * -     * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since -     * it was being stored.  This Doesn't solve all cases of -     * recursive lookup but for the most common types it does. -     */ -    first_ifindex = nexthop_tab[0].ifindex; -    nexthop_addr = nexthop_tab[0].nexthop_addr; -    if (first_ifindex > 0) { -      /* found: first ifindex is non-recursive nexthop */ - -      if (lookup > 0) { -	/* Report non-recursive success after first lookup */ +	int lookup; +	uint32_t route_metric = 0xFFFFFFFF; +	uint8_t protocol_distance = 0xFF; + +	qpim_nexthop_lookups++; + +	for (lookup = 0; lookup < max_lookup; ++lookup) { +		int num_ifindex; +		int first_ifindex; +		struct prefix nexthop_addr; + +		num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, tab_size, +							  addr); +		if (num_ifindex < 1) { +			if (PIM_DEBUG_ZEBRA) { +				char addr_str[INET_ADDRSTRLEN]; +				pim_inet4_dump("<addr?>", addr, addr_str, +					       sizeof(addr_str)); +				zlog_debug( +					"%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s", +					__FILE__, __PRETTY_FUNCTION__, lookup, +					max_lookup, addr_str); +			} +			return -1; +		} + +		if (lookup < 1) { +			/* this is the non-recursive lookup - save original +			 * metric/distance */ +			route_metric = nexthop_tab[0].route_metric; +			protocol_distance = nexthop_tab[0].protocol_distance; +		} + +		/* +		 * FIXME: Non-recursive nexthop ensured only for first ifindex. +		 * However, recursive route lookup should really be fixed in +		 * zebra daemon. +		 * See also TODO T24. +		 * +		 * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since +		 * it was being stored.  This Doesn't solve all cases of +		 * recursive lookup but for the most common types it does. +		 */ +		first_ifindex = nexthop_tab[0].ifindex; +		nexthop_addr = nexthop_tab[0].nexthop_addr; +		if (first_ifindex > 0) { +			/* found: first ifindex is non-recursive nexthop */ + +			if (lookup > 0) { +				/* Report non-recursive success after first +				 * lookup */ +				if (PIM_DEBUG_ZEBRA) { +					char addr_str[INET_ADDRSTRLEN]; +					pim_inet4_dump("<addr?>", addr, +						       addr_str, +						       sizeof(addr_str)); +					zlog_debug( +						"%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d", +						__FILE__, __PRETTY_FUNCTION__, +						lookup, max_lookup, +						first_ifindex, addr_str, +						nexthop_tab[0] +							.protocol_distance, +						nexthop_tab[0].route_metric); +				} + +				/* use last address as nexthop address */ +				nexthop_tab[0].nexthop_addr.u.prefix4 = addr; + +				/* report original route metric/distance */ +				nexthop_tab[0].route_metric = route_metric; +				nexthop_tab[0].protocol_distance = +					protocol_distance; +			} + +			return num_ifindex; +		} + +		if (PIM_DEBUG_ZEBRA) { +			char addr_str[INET_ADDRSTRLEN]; +			char nexthop_str[PREFIX_STRLEN]; +			pim_inet4_dump("<addr?>", addr, addr_str, +				       sizeof(addr_str)); +			pim_addr_dump("<nexthop?>", &nexthop_addr, nexthop_str, +				      sizeof(nexthop_str)); +			zlog_debug( +				"%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", +				__FILE__, __PRETTY_FUNCTION__, lookup, +				max_lookup, nexthop_str, addr_str, +				nexthop_tab[0].protocol_distance, +				nexthop_tab[0].route_metric); +		} + +		addr = +			nexthop_addr.u.prefix4; /* use nexthop addr for +						   recursive lookup */ + +	} /* for (max_lookup) */ +  	if (PIM_DEBUG_ZEBRA) { -	  char addr_str[INET_ADDRSTRLEN]; -	  pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -	  zlog_debug("%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d", -		     __FILE__, __PRETTY_FUNCTION__, -		     lookup, max_lookup, first_ifindex, addr_str, -		     nexthop_tab[0].protocol_distance, -		     nexthop_tab[0].route_metric); +		char addr_str[INET_ADDRSTRLEN]; +		pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); +		zlog_warn( +			"%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s", +			__FILE__, __PRETTY_FUNCTION__, lookup, max_lookup, +			addr_str);  	} -	/* use last address as nexthop address */ -	nexthop_tab[0].nexthop_addr.u.prefix4 = addr; - -	/* report original route metric/distance */ -	nexthop_tab[0].route_metric = route_metric; -	nexthop_tab[0].protocol_distance = protocol_distance; -      } - -      return num_ifindex; -    } - -    if (PIM_DEBUG_ZEBRA) { -      char addr_str[INET_ADDRSTRLEN]; -      char nexthop_str[PREFIX_STRLEN]; -      pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -      pim_addr_dump("<nexthop?>", &nexthop_addr, nexthop_str, sizeof(nexthop_str)); -      zlog_debug("%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", -		__FILE__, __PRETTY_FUNCTION__, -		lookup, max_lookup, nexthop_str, addr_str, -		nexthop_tab[0].protocol_distance, -		nexthop_tab[0].route_metric); -    } - -    addr = nexthop_addr.u.prefix4; /* use nexthop addr for recursive lookup */ - -  } /* for (max_lookup) */ - -  if (PIM_DEBUG_ZEBRA) { -    char addr_str[INET_ADDRSTRLEN]; -    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); -    zlog_warn("%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s", -	      __FILE__, __PRETTY_FUNCTION__, -	      lookup, max_lookup, addr_str); -  } - -  return -2; +	return -2;  } -void -pim_zlookup_show_ip_multicast (struct vty *vty) +void pim_zlookup_show_ip_multicast(struct vty *vty)  { -  vty_out(vty, "Zclient lookup socket: "); -  if (zlookup) { -    vty_out (vty, "%d failures=%d\n", zlookup->sock, -            zlookup->fail); -  } -  else { -    vty_out (vty, "<null zclient>\n"); -  } +	vty_out(vty, "Zclient lookup socket: "); +	if (zlookup) { +		vty_out(vty, "%d failures=%d\n", zlookup->sock, zlookup->fail); +	} else { +		vty_out(vty, "<null zclient>\n"); +	}  } -int -pim_zlookup_sg_statistics (struct channel_oil *c_oil) +int pim_zlookup_sg_statistics(struct channel_oil *c_oil)  { -  struct stream *s = zlookup->obuf; -  uint16_t command = 0; -  unsigned long long lastused; -  struct prefix_sg sg; -  int count = 0; -  int ret; -  struct interface *ifp = pim_if_find_by_vif_index (c_oil->oil.mfcc_parent); - -  if (PIM_DEBUG_ZEBRA) -    { -      struct prefix_sg more; - -      more.src = c_oil->oil.mfcc_origin; -      more.grp = c_oil->oil.mfcc_mcastgrp; -      zlog_debug ("Sending Request for New Channel Oil Information(%s) VIIF %d", -            pim_str_sg_dump (&more), c_oil->oil.mfcc_parent); -    } - -  if (!ifp) -    return -1; - -  stream_reset (s); -  zclient_create_header (s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); -  stream_put_in_addr (s, &c_oil->oil.mfcc_origin); -  stream_put_in_addr (s, &c_oil->oil.mfcc_mcastgrp); -  stream_putl (s,  ifp->ifindex); -  stream_putw_at(s, 0, stream_get_endp(s)); - -  count = stream_get_endp (s); -  ret = writen (zlookup->sock, s->data, count); -  if (ret <= 0) -    { -      zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", -               __FILE__, __PRETTY_FUNCTION__, errno); -      return -1; -    } - -  s = zlookup->ibuf; - -  while (command != ZEBRA_IPMR_ROUTE_STATS) -    { -      int err; -      uint16_t length = 0; -      vrf_id_t vrf_id; -      u_char marker; -      u_char version; - -      stream_reset (s); -      err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, -				 &vrf_id, &command); -      if (err < 0) -        { -          zlog_err ("%s %s: zclient_read_header() failed", -                 __FILE__, __PRETTY_FUNCTION__); -        zclient_lookup_failed(zlookup); -        return -1; -        } -    } - -  sg.src.s_addr = stream_get_ipv4 (s); -  sg.grp.s_addr = stream_get_ipv4 (s); -  if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr || -      sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) -    { -       zlog_err ("%s: Received wrong %s information", -		 __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); -       zclient_lookup_failed (zlookup); -       return -3; -    } - -  stream_get (&lastused, s, sizeof (lastused)); -  ret = stream_getl (s); - -  if (PIM_DEBUG_ZEBRA) -    zlog_debug ("Received %lld for %s success: %d", lastused, pim_str_sg_dump (&sg), ret); - -  c_oil->cc.lastused = lastused; - -  return 0; +	struct stream *s = zlookup->obuf; +	uint16_t command = 0; +	unsigned long long lastused; +	struct prefix_sg sg; +	int count = 0; +	int ret; +	struct interface *ifp = +		pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + +	if (PIM_DEBUG_ZEBRA) { +		struct prefix_sg more; + +		more.src = c_oil->oil.mfcc_origin; +		more.grp = c_oil->oil.mfcc_mcastgrp; +		zlog_debug( +			"Sending Request for New Channel Oil Information(%s) VIIF %d", +			pim_str_sg_dump(&more), c_oil->oil.mfcc_parent); +	} + +	if (!ifp) +		return -1; + +	stream_reset(s); +	zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); +	stream_put_in_addr(s, &c_oil->oil.mfcc_origin); +	stream_put_in_addr(s, &c_oil->oil.mfcc_mcastgrp); +	stream_putl(s, ifp->ifindex); +	stream_putw_at(s, 0, stream_get_endp(s)); + +	count = stream_get_endp(s); +	ret = writen(zlookup->sock, s->data, count); +	if (ret <= 0) { +		zlog_err( +			"%s %s: writen() failure: %d writing to zclient lookup socket", +			__FILE__, __PRETTY_FUNCTION__, errno); +		return -1; +	} + +	s = zlookup->ibuf; + +	while (command != ZEBRA_IPMR_ROUTE_STATS) { +		int err; +		uint16_t length = 0; +		vrf_id_t vrf_id; +		u_char marker; +		u_char version; + +		stream_reset(s); +		err = zclient_read_header(s, zlookup->sock, &length, &marker, +					  &version, &vrf_id, &command); +		if (err < 0) { +			zlog_err("%s %s: zclient_read_header() failed", +				 __FILE__, __PRETTY_FUNCTION__); +			zclient_lookup_failed(zlookup); +			return -1; +		} +	} + +	sg.src.s_addr = stream_get_ipv4(s); +	sg.grp.s_addr = stream_get_ipv4(s); +	if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr +	    || sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) { +		zlog_err("%s: Received wrong %s information", +			 __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); +		zclient_lookup_failed(zlookup); +		return -3; +	} + +	stream_get(&lastused, s, sizeof(lastused)); +	ret = stream_getl(s); + +	if (PIM_DEBUG_ZEBRA) +		zlog_debug("Received %lld for %s success: %d", lastused, +			   pim_str_sg_dump(&sg), ret); + +	c_oil->cc.lastused = lastused; +	return 0;  } diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index 08c8768d14..d168464ce5 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -27,21 +27,20 @@  #define PIM_NEXTHOP_LOOKUP_MAX (3) /* max. recursive route lookup */  struct pim_zlookup_nexthop { -  struct prefix  nexthop_addr; -  ifindex_t      ifindex; -  uint32_t       route_metric; -  uint8_t        protocol_distance; +	struct prefix nexthop_addr; +	ifindex_t ifindex; +	uint32_t route_metric; +	uint8_t protocol_distance;  }; -void zclient_lookup_new (void); -void zclient_lookup_free (void); +void zclient_lookup_new(void); +void zclient_lookup_free(void);  int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], -			   const int tab_size, -			   struct in_addr addr, +			   const int tab_size, struct in_addr addr,  			   int max_lookup); -void pim_zlookup_show_ip_multicast (struct vty *vty); +void pim_zlookup_show_ip_multicast(struct vty *vty); -int pim_zlookup_sg_statistics (struct channel_oil *c_oil); +int pim_zlookup_sg_statistics(struct channel_oil *c_oil);  #endif /* PIM_ZLOOKUP_H */ diff --git a/pimd/pimd.c b/pimd/pimd.c index b1d566f51b..89b235bed1 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -45,289 +45,272 @@  #include "pim_zlookup.h"  #include "pim_nht.h" -const char *const PIM_ALL_SYSTEMS      = MCAST_ALL_SYSTEMS; -const char *const PIM_ALL_ROUTERS      = MCAST_ALL_ROUTERS; -const char *const PIM_ALL_PIM_ROUTERS  = MCAST_ALL_PIM_ROUTERS; +const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; +const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; +const char *const PIM_ALL_PIM_ROUTERS = MCAST_ALL_PIM_ROUTERS;  const char *const PIM_ALL_IGMP_ROUTERS = MCAST_ALL_IGMP_ROUTERS; -struct thread_master     *master = NULL; -uint32_t                  qpim_debugs = 0; -int                       qpim_mroute_socket_fd = -1; -int64_t                   qpim_mroute_socket_creation = 0; /* timestamp of creation */ -int                       qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ -struct pim_assert_metric  qpim_infinite_assert_metric; -long                      qpim_rpf_cache_refresh_delay_msec = 50; -struct thread            *qpim_rpf_cache_refresher = NULL; -int64_t                   qpim_rpf_cache_refresh_requests = 0; -int64_t                   qpim_rpf_cache_refresh_events = 0; -int64_t                   qpim_rpf_cache_refresh_last =  0; -struct list              *qpim_ssmpingd_list = NULL; -struct in_addr            qpim_ssmpingd_group_addr; -int64_t                   qpim_scan_oil_events = 0; -int64_t                   qpim_scan_oil_last = 0; -int64_t                   qpim_mroute_add_events = 0; -int64_t                   qpim_mroute_add_last = 0; -int64_t                   qpim_mroute_del_events = 0; -int64_t                   qpim_mroute_del_last = 0; -struct list              *qpim_static_route_list = NULL; -unsigned int              qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; -signed int                qpim_rp_keep_alive_time = 0; -int64_t                   qpim_nexthop_lookups = 0; -int                       qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; -uint8_t                   qpim_ecmp_enable = 0; -uint8_t                   qpim_ecmp_rebalance_enable = 0; -struct pim_instance       *pimg = NULL; +struct thread_master *master = NULL; +uint32_t qpim_debugs = 0; +int qpim_mroute_socket_fd = -1; +int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ +int qpim_t_periodic = +	PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ +struct pim_assert_metric qpim_infinite_assert_metric; +long qpim_rpf_cache_refresh_delay_msec = 50; +struct thread *qpim_rpf_cache_refresher = NULL; +int64_t qpim_rpf_cache_refresh_requests = 0; +int64_t qpim_rpf_cache_refresh_events = 0; +int64_t qpim_rpf_cache_refresh_last = 0; +struct list *qpim_ssmpingd_list = NULL; +struct in_addr qpim_ssmpingd_group_addr; +int64_t qpim_scan_oil_events = 0; +int64_t qpim_scan_oil_last = 0; +int64_t qpim_mroute_add_events = 0; +int64_t qpim_mroute_add_last = 0; +int64_t qpim_mroute_del_events = 0; +int64_t qpim_mroute_del_last = 0; +struct list *qpim_static_route_list = NULL; +unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; +signed int qpim_rp_keep_alive_time = 0; +int64_t qpim_nexthop_lookups = 0; +int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; +uint8_t qpim_ecmp_enable = 0; +uint8_t qpim_ecmp_rebalance_enable = 0; +struct pim_instance *pimg = NULL;  int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;  int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; -static struct pim_instance *pim_instance_init (vrf_id_t vrf_id, afi_t afi); -static void pim_instance_terminate (void); +static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi); +static void pim_instance_terminate(void); -static int -pim_vrf_new (struct vrf *vrf) +static int pim_vrf_new(struct vrf *vrf)  { -  zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); -  return 0; +	zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); +	return 0;  } -static int -pim_vrf_delete (struct vrf *vrf) +static int pim_vrf_delete(struct vrf *vrf)  { -  zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); -  return 0; +	zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); +	return 0;  } -static int -pim_vrf_enable (struct vrf *vrf) +static int pim_vrf_enable(struct vrf *vrf)  { -  if (!vrf) // unexpected -    return -1; - -  if (vrf->vrf_id == VRF_DEFAULT) -    { -      pimg = pim_instance_init (VRF_DEFAULT, AFI_IP); -      if (pimg == NULL) -        { -          zlog_err ("%s %s: pim class init failure ", __FILE__, -                    __PRETTY_FUNCTION__); -          /* -           * We will crash and burn otherwise -           */ -          exit(1); -      } - -    pimg->send_v6_secondary = 1; - -    } -  return 0; +	if (!vrf) // unexpected +		return -1; + +	if (vrf->vrf_id == VRF_DEFAULT) { +		pimg = pim_instance_init(VRF_DEFAULT, AFI_IP); +		if (pimg == NULL) { +			zlog_err("%s %s: pim class init failure ", __FILE__, +				 __PRETTY_FUNCTION__); +			/* +			 * We will crash and burn otherwise +			 */ +			exit(1); +		} + +		pimg->send_v6_secondary = 1; +	} +	return 0;  } -static int -pim_vrf_disable (struct vrf *vrf) +static int pim_vrf_disable(struct vrf *vrf)  { -  if (vrf->vrf_id == VRF_DEFAULT) -    return 0; +	if (vrf->vrf_id == VRF_DEFAULT) +		return 0; -  if (vrf->vrf_id == VRF_DEFAULT) -    pim_instance_terminate (); +	if (vrf->vrf_id == VRF_DEFAULT) +		pim_instance_terminate(); -  /* Note: This is a callback, the VRF will be deleted by the caller. */ -  return 0; +	/* Note: This is a callback, the VRF will be deleted by the caller. */ +	return 0;  } -void -pim_vrf_init (void) +void pim_vrf_init(void)  { -  vrf_init (pim_vrf_new, -	    pim_vrf_enable, -	    pim_vrf_disable, -	    pim_vrf_delete); +	vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete);  } -static void -pim_vrf_terminate (void) +static void pim_vrf_terminate(void)  { -  vrf_terminate (); +	vrf_terminate();  }  /* Key generate for pim->rpf_hash */ -static unsigned int -pim_rpf_hash_key (void *arg) +static unsigned int pim_rpf_hash_key(void *arg)  { -  struct pim_nexthop_cache *r = (struct pim_nexthop_cache *) arg; +	struct pim_nexthop_cache *r = (struct pim_nexthop_cache *)arg; -  return jhash_1word (r->rpf.rpf_addr.u.prefix4.s_addr, 0); +	return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0);  }  /* Compare pim->rpf_hash node data */ -static int -pim_rpf_equal (const void *arg1, const void *arg2) +static int pim_rpf_equal(const void *arg1, const void *arg2)  { -  const struct pim_nexthop_cache *r1 = -    (const struct pim_nexthop_cache *) arg1; -  const struct pim_nexthop_cache *r2 = -    (const struct pim_nexthop_cache *) arg2; +	const struct pim_nexthop_cache *r1 = +		(const struct pim_nexthop_cache *)arg1; +	const struct pim_nexthop_cache *r2 = +		(const struct pim_nexthop_cache *)arg2; -  return prefix_same (&r1->rpf.rpf_addr, &r2->rpf.rpf_addr); +	return prefix_same(&r1->rpf.rpf_addr, &r2->rpf.rpf_addr);  }  /* Cleanup pim->rpf_hash each node data */ -static void -pim_rp_list_hash_clean (void *data) +static void pim_rp_list_hash_clean(void *data)  { -  struct pim_nexthop_cache *pnc; +	struct pim_nexthop_cache *pnc; -  pnc = (struct pim_nexthop_cache *) data; -  if (pnc->rp_list->count) -    list_delete_all_node (pnc->rp_list); -  if (pnc->upstream_list->count) -    list_delete_all_node (pnc->upstream_list); +	pnc = (struct pim_nexthop_cache *)data; +	if (pnc->rp_list->count) +		list_delete_all_node(pnc->rp_list); +	if (pnc->upstream_list->count) +		list_delete_all_node(pnc->upstream_list);  } -void -pim_prefix_list_update (struct prefix_list *plist) +void pim_prefix_list_update(struct prefix_list *plist)  { -    pim_rp_prefix_list_update (plist); -    pim_ssm_prefix_list_update (plist); -    pim_upstream_spt_prefix_list_update (plist); +	pim_rp_prefix_list_update(plist); +	pim_ssm_prefix_list_update(plist); +	pim_upstream_spt_prefix_list_update(plist);  } -static void -pim_instance_terminate (void) +static void pim_instance_terminate(void)  { -  /* Traverse and cleanup rpf_hash */ -  if (pimg->rpf_hash) -    { -      hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean); -      hash_free (pimg->rpf_hash); -      pimg->rpf_hash = NULL; -    } - -  if (pimg->ssm_info) -    { -      pim_ssm_terminate (pimg->ssm_info); -      pimg->ssm_info = NULL; -    } - -  XFREE (MTYPE_PIM_PIM_INSTANCE, pimg); +	/* Traverse and cleanup rpf_hash */ +	if (pimg->rpf_hash) { +		hash_clean(pimg->rpf_hash, (void *)pim_rp_list_hash_clean); +		hash_free(pimg->rpf_hash); +		pimg->rpf_hash = NULL; +	} + +	if (pimg->ssm_info) { +		pim_ssm_terminate(pimg->ssm_info); +		pimg->ssm_info = NULL; +	} + +	XFREE(MTYPE_PIM_PIM_INSTANCE, pimg);  }  static void pim_free()  { -  pim_ssmpingd_destroy(); +	pim_ssmpingd_destroy(); -  pim_oil_terminate (); +	pim_oil_terminate(); -  pim_upstream_terminate (); +	pim_upstream_terminate(); -  if (qpim_static_route_list) -     list_free(qpim_static_route_list); +	if (qpim_static_route_list) +		list_free(qpim_static_route_list); -  pim_if_terminate (); -  pim_rp_free (); +	pim_if_terminate(); +	pim_rp_free(); -  pim_route_map_terminate(); +	pim_route_map_terminate(); -  zclient_lookup_free (); +	zclient_lookup_free(); -  zprivs_terminate(&pimd_privs); +	zprivs_terminate(&pimd_privs);  } -static struct pim_instance * -pim_instance_init (vrf_id_t vrf_id, afi_t afi) +static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi)  { -  struct pim_instance *pim; +	struct pim_instance *pim; -  pim = XCALLOC (MTYPE_PIM_PIM_INSTANCE, sizeof (struct pim_instance)); -  if (!pim) -    return NULL; +	pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance)); +	if (!pim) +		return NULL; -  pim->vrf_id = vrf_id; -  pim->afi = afi; +	pim->vrf_id = vrf_id; +	pim->afi = afi; -  pim->spt.switchover = PIM_SPT_IMMEDIATE; -  pim->spt.plist = NULL; +	pim->spt.switchover = PIM_SPT_IMMEDIATE; +	pim->spt.plist = NULL; -  pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal, NULL); +	pim->rpf_hash = +		hash_create_size(256, pim_rpf_hash_key, pim_rpf_equal, NULL); -  if (PIM_DEBUG_ZEBRA) -    zlog_debug ("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); +	if (PIM_DEBUG_ZEBRA) +		zlog_debug("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); -  pim->ssm_info = pim_ssm_init (vrf_id); -  if (!pim->ssm_info) { -    pim_instance_terminate (); -    return NULL; -  } +	pim->ssm_info = pim_ssm_init(vrf_id); +	if (!pim->ssm_info) { +		pim_instance_terminate(); +		return NULL; +	} -  return pim; +	return pim;  }  void pim_init()  { -  qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; - -  pim_rp_init (); - -  if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { -    zlog_err("%s %s: could not solve %s to group address: errno=%d: %s", -	     __FILE__, __PRETTY_FUNCTION__, -	     PIM_ALL_PIM_ROUTERS, errno, safe_strerror(errno)); -    zassert(0); -    return; -  } - -  pim_oil_init (); - -  pim_upstream_init (); - -  qpim_static_route_list = list_new(); -  if (!qpim_static_route_list) { -    zlog_err("%s %s: failure: static_route_list=list_new()", -        __FILE__, __PRETTY_FUNCTION__); -    return; -  } -  qpim_static_route_list->del = (void (*)(void *)) pim_static_route_free; - -  pim_mroute_socket_enable(); - - -  /* -    RFC 4601: 4.6.3.  Assert Metrics - -    assert_metric -    infinite_assert_metric() { -    return {1,infinity,infinity,0} -    } -  */ -  qpim_infinite_assert_metric.rpt_bit_flag      = 1; -  qpim_infinite_assert_metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; -  qpim_infinite_assert_metric.route_metric      = PIM_ASSERT_ROUTE_METRIC_MAX; -  qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY; - -  pim_if_init(); -  pim_cmd_init(); -  pim_ssmpingd_init(); +	qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; + +	pim_rp_init(); + +	if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { +		zlog_err( +			"%s %s: could not solve %s to group address: errno=%d: %s", +			__FILE__, __PRETTY_FUNCTION__, PIM_ALL_PIM_ROUTERS, +			errno, safe_strerror(errno)); +		zassert(0); +		return; +	} + +	pim_oil_init(); + +	pim_upstream_init(); + +	qpim_static_route_list = list_new(); +	if (!qpim_static_route_list) { +		zlog_err("%s %s: failure: static_route_list=list_new()", +			 __FILE__, __PRETTY_FUNCTION__); +		return; +	} +	qpim_static_route_list->del = (void (*)(void *))pim_static_route_free; + +	pim_mroute_socket_enable(); + + +	/* +	  RFC 4601: 4.6.3.  Assert Metrics + +	  assert_metric +	  infinite_assert_metric() { +	  return {1,infinity,infinity,0} +	  } +	*/ +	qpim_infinite_assert_metric.rpt_bit_flag = 1; +	qpim_infinite_assert_metric.metric_preference = +		PIM_ASSERT_METRIC_PREFERENCE_MAX; +	qpim_infinite_assert_metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; +	qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY; + +	pim_if_init(); +	pim_cmd_init(); +	pim_ssmpingd_init();  }  void pim_terminate()  { -  struct zclient *zclient; +	struct zclient *zclient; -  pim_free(); +	pim_free(); -  /* reverse prefix_list_init */ -  prefix_list_add_hook (NULL); -  prefix_list_delete_hook (NULL); -  prefix_list_reset (); +	/* reverse prefix_list_init */ +	prefix_list_add_hook(NULL); +	prefix_list_delete_hook(NULL); +	prefix_list_reset(); -  pim_vrf_terminate (); +	pim_vrf_terminate(); -  zclient = pim_zebra_zclient_get (); -  if (zclient) -    { -      zclient_stop (zclient); -      zclient_free (zclient); -    } +	zclient = pim_zebra_zclient_get(); +	if (zclient) { +		zclient_stop(zclient); +		zclient_free(zclient); +	}  } diff --git a/pimd/pimd.h b/pimd/pimd.h index 18520f57e1..7934bce2d4 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -65,10 +65,9 @@   * |   Number of Joined Sources    |   Number of Pruned Sources    |   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   */ -#define PIM_JP_GROUP_HEADER_SIZE     (PIM_ENCODED_IPV4_UCAST_SIZE + \ -                                      1 + 1 + 2 +                   \ -                                      PIM_ENCODED_IPV4_GROUP_SIZE + \ -                                      2 + 2) +#define PIM_JP_GROUP_HEADER_SIZE                                               \ +	(PIM_ENCODED_IPV4_UCAST_SIZE + 1 + 1 + 2 + PIM_ENCODED_IPV4_GROUP_SIZE \ +	 + 2 + 2)  #define PIM_PROTO_VERSION             (2) @@ -108,7 +107,6 @@  #define PIM_MASK_MSDP_PACKETS        (1 << 20)  #define PIM_MASK_MSDP_INTERNAL       (1 << 21) -  /* PIM error codes */  #define PIM_SUCCESS                0  #define PIM_MALLOC_FAIL           -1 @@ -127,34 +125,34 @@ const char *const PIM_ALL_ROUTERS;  const char *const PIM_ALL_PIM_ROUTERS;  const char *const PIM_ALL_IGMP_ROUTERS; -extern struct thread_master     *master; +extern struct thread_master *master;  extern struct zebra_privs_t pimd_privs; -uint32_t                  qpim_debugs; -int                       qpim_mroute_socket_fd; -int64_t                   qpim_mroute_socket_creation; /* timestamp of creation */ -struct in_addr            qpim_all_pim_routers_addr; -int                       qpim_t_periodic; /* Period between Join/Prune Messages */ -struct pim_assert_metric  qpim_infinite_assert_metric; -long                      qpim_rpf_cache_refresh_delay_msec; -struct thread            *qpim_rpf_cache_refresher; -int64_t                   qpim_rpf_cache_refresh_requests; -int64_t                   qpim_rpf_cache_refresh_events; -int64_t                   qpim_rpf_cache_refresh_last; -struct list              *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */ -struct in_addr            qpim_ssmpingd_group_addr; -int64_t                   qpim_scan_oil_events; -int64_t                   qpim_scan_oil_last; -int64_t                   qpim_mroute_add_events; -int64_t                   qpim_mroute_add_last; -int64_t                   qpim_mroute_del_events; -int64_t                   qpim_mroute_del_last; -int64_t                   qpim_nexthop_lookups; -struct list              *qpim_static_route_list; /* list of routes added statically */ -extern unsigned int       qpim_keep_alive_time; -extern signed int         qpim_rp_keep_alive_time; -extern int                qpim_packet_process; -extern uint8_t            qpim_ecmp_enable; -extern uint8_t            qpim_ecmp_rebalance_enable; +uint32_t qpim_debugs; +int qpim_mroute_socket_fd; +int64_t qpim_mroute_socket_creation; /* timestamp of creation */ +struct in_addr qpim_all_pim_routers_addr; +int qpim_t_periodic; /* Period between Join/Prune Messages */ +struct pim_assert_metric qpim_infinite_assert_metric; +long qpim_rpf_cache_refresh_delay_msec; +struct thread *qpim_rpf_cache_refresher; +int64_t qpim_rpf_cache_refresh_requests; +int64_t qpim_rpf_cache_refresh_events; +int64_t qpim_rpf_cache_refresh_last; +struct list *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */ +struct in_addr qpim_ssmpingd_group_addr; +int64_t qpim_scan_oil_events; +int64_t qpim_scan_oil_last; +int64_t qpim_mroute_add_events; +int64_t qpim_mroute_add_last; +int64_t qpim_mroute_del_events; +int64_t qpim_mroute_del_last; +int64_t qpim_nexthop_lookups; +struct list *qpim_static_route_list; /* list of routes added statically */ +extern unsigned int qpim_keep_alive_time; +extern signed int qpim_rp_keep_alive_time; +extern int qpim_packet_process; +extern uint8_t qpim_ecmp_enable; +extern uint8_t qpim_ecmp_rebalance_enable;  #define PIM_DEFAULT_PACKET_PROCESS 3 @@ -239,36 +237,35 @@ extern int32_t qpim_register_probe_time;  #define PIM_DONT_DEBUG_MSDP_INTERNAL       (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL)  enum pim_spt_switchover { -  PIM_SPT_IMMEDIATE, -  PIM_SPT_INFINITY, +	PIM_SPT_IMMEDIATE, +	PIM_SPT_INFINITY,  };  /* Per VRF PIM DB */ -struct pim_instance -{ -  afi_t afi; -  vrf_id_t vrf_id; +struct pim_instance { +	afi_t afi; +	vrf_id_t vrf_id; + +	struct { +		enum pim_spt_switchover switchover; +		char *plist; +	} spt; -  struct { -    enum pim_spt_switchover switchover; -    char *plist; -  } spt; +	struct hash *rpf_hash; -  struct hash *rpf_hash; +	void *ssm_info; /* per-vrf SSM configuration */ -  void *ssm_info; /* per-vrf SSM configuration */ -   -  int send_v6_secondary; +	int send_v6_secondary;  }; -extern struct pim_instance *pimg; //Pim Global Instance +extern struct pim_instance *pimg; // Pim Global Instance  void pim_init(void);  void pim_terminate(void); -extern void pim_route_map_init (void); +extern void pim_route_map_init(void);  extern void pim_route_map_terminate(void); -void pim_vrf_init (void); -void pim_prefix_list_update (struct prefix_list *plist); +void pim_vrf_init(void); +void pim_prefix_list_update(struct prefix_list *plist);  #endif /* PIMD_H */ diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index f363152ad4..14ec9fb02b 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -36,114 +36,114 @@ const char *prog_name = 0;  static int iface_solve_index(const char *ifname)  { -  struct if_nameindex *ini; -  ifindex_t ifindex = -1; -  int i; - -  if (!ifname) -    return -1; - -  ini = if_nameindex(); -  if (!ini) { -    int err = errno; -    fprintf(stderr, -	    "%s: interface=%s: failure solving index: errno=%d: %s\n", -	    prog_name, ifname, err, strerror(err)); -    errno = err; -    return -1; -  } - -  for (i = 0; ini[i].if_index; ++i) { +	struct if_nameindex *ini; +	ifindex_t ifindex = -1; +	int i; + +	if (!ifname) +		return -1; + +	ini = if_nameindex(); +	if (!ini) { +		int err = errno; +		fprintf(stderr, +			"%s: interface=%s: failure solving index: errno=%d: %s\n", +			prog_name, ifname, err, strerror(err)); +		errno = err; +		return -1; +	} + +	for (i = 0; ini[i].if_index; ++i) {  #if 0      fprintf(stderr,  	    "%s: interface=%s matching against local ifname=%s ifindex=%d\n",  	    prog_name, ifname, ini[i].if_name, ini[i].if_index);  #endif -    if (!strcmp(ini[i].if_name, ifname)) { -      ifindex = ini[i].if_index; -      break; -    } -  } +		if (!strcmp(ini[i].if_name, ifname)) { +			ifindex = ini[i].if_index; +			break; +		} +	} -  if_freenameindex(ini); +	if_freenameindex(ini); -  return ifindex; +	return ifindex;  }  int main(int argc, const char *argv[])  { -  struct in_addr group_addr; -  struct in_addr source_addr; -  const char *ifname; -  const char *group; -  const char *source; -  ifindex_t ifindex; -  int result; -  int fd; - -  prog_name = argv[0]; - -  fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); -  if (fd < 0) { -    fprintf(stderr, -	    "%s: could not create socket: socket(): errno=%d: %s\n", -	    prog_name, errno, strerror(errno)); -    exit(1); -  } - -  if (argc != 4) { -    fprintf(stderr, -	    "usage:   %s interface group     source\n" -	    "example: %s eth0      232.1.1.1 1.1.1.1\n", -	    prog_name, prog_name); -    exit(1); -  } - -  ifname = argv[1]; -  group  = argv[2]; -  source = argv[3]; - -  ifindex = iface_solve_index(ifname); -  if (ifindex < 0) { -    fprintf(stderr, "%s: could not find interface: %s\n", -	    prog_name, ifname); -    exit(1); -  } - -  result = inet_pton(AF_INET, group, &group_addr); -  if (result <= 0) { -    fprintf(stderr, "%s: bad group address: %s\n", -	    prog_name, group); -    exit(1); -  } - -  result = inet_pton(AF_INET, source, &source_addr); -  if (result <= 0) { -    fprintf(stderr, "%s: bad source address: %s\n", -	    prog_name, source); -    exit(1); -  } - -  result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); -  if (result) { -    fprintf(stderr, -	    "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", -	    prog_name, fd, group, source, ifindex, ifname, -	    errno, strerror(errno)); -    exit(1); -  } - -  printf("%s: joined channel (S,G)=(%s,%s) on interface %s\n", -	 prog_name, source, group, ifname); - -  printf("%s: waiting...\n", prog_name); - -  getchar(); - -  close(fd); - -  printf("%s: left channel (S,G)=(%s,%s) on interface %s\n", -	 prog_name, source, group, ifname); - -  exit(0); +	struct in_addr group_addr; +	struct in_addr source_addr; +	const char *ifname; +	const char *group; +	const char *source; +	ifindex_t ifindex; +	int result; +	int fd; + +	prog_name = argv[0]; + +	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +	if (fd < 0) { +		fprintf(stderr, +			"%s: could not create socket: socket(): errno=%d: %s\n", +			prog_name, errno, strerror(errno)); +		exit(1); +	} + +	if (argc != 4) { +		fprintf(stderr, +			"usage:   %s interface group     source\n" +			"example: %s eth0      232.1.1.1 1.1.1.1\n", +			prog_name, prog_name); +		exit(1); +	} + +	ifname = argv[1]; +	group = argv[2]; +	source = argv[3]; + +	ifindex = iface_solve_index(ifname); +	if (ifindex < 0) { +		fprintf(stderr, "%s: could not find interface: %s\n", prog_name, +			ifname); +		exit(1); +	} + +	result = inet_pton(AF_INET, group, &group_addr); +	if (result <= 0) { +		fprintf(stderr, "%s: bad group address: %s\n", prog_name, +			group); +		exit(1); +	} + +	result = inet_pton(AF_INET, source, &source_addr); +	if (result <= 0) { +		fprintf(stderr, "%s: bad source address: %s\n", prog_name, +			source); +		exit(1); +	} + +	result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); +	if (result) { +		fprintf(stderr, +			"%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", +			prog_name, fd, group, source, ifindex, ifname, errno, +			strerror(errno)); +		exit(1); +	} + +	printf("%s: joined channel (S,G)=(%s,%s) on interface %s\n", prog_name, +	       source, group, ifname); + +	printf("%s: waiting...\n", prog_name); + +	getchar(); + +	close(fd); + +	printf("%s: left channel (S,G)=(%s,%s) on interface %s\n", prog_name, +	       source, group, ifname); + +	exit(0);  }  | 
