diff options
Diffstat (limited to 'pimd/pim_hello.c')
| -rw-r--r-- | pimd/pim_hello.c | 878 | 
1 files changed, 439 insertions, 439 deletions
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 */  }  | 
