diff options
Diffstat (limited to 'zebra/zebra_rnh.c')
| -rw-r--r-- | zebra/zebra_rnh.c | 1610 | 
1 files changed, 792 insertions, 818 deletions
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c82712b9cc..8a326c27fc 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -48,22 +48,23 @@  #include "zebra/interface.h"  #include "zebra/zebra_memory.h" -static void free_state(vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn); +static void free_state(vrf_id_t vrf_id, struct route_entry *re, +		       struct route_node *rn);  static void copy_state(struct rnh *rnh, struct route_entry *re,  		       struct route_node *rn); -#define lookup_rnh_table(v, f)		         \ -({						 \ -  struct zebra_vrf *zvrf;                        \ -  struct route_table *t = NULL;                  \ -  zvrf = zebra_vrf_lookup_by_id(v);              \ -  if (zvrf)                                      \ -    t = zvrf->rnh_table[family2afi(f)];	         \ -  t;                                             \ -}) +#define lookup_rnh_table(v, f)                                                 \ +	({                                                                     \ +		struct zebra_vrf *zvrf;                                        \ +		struct route_table *t = NULL;                                  \ +		zvrf = zebra_vrf_lookup_by_id(v);                              \ +		if (zvrf)                                                      \ +			t = zvrf->rnh_table[family2afi(f)];                    \ +		t;                                                             \ +	})  static int compare_state(struct route_entry *r1, struct route_entry *r2);  static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, -                       vrf_id_t vrf_id); +		       vrf_id_t vrf_id);  static void print_rnh(struct route_node *rn, struct vty *vty);  int zebra_rnh_ip_default_route = 0; @@ -72,541 +73,526 @@ int zebra_rnh_ipv6_default_route = 0;  static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family,  						rnh_type_t type)  { -  struct zebra_vrf *zvrf; -  struct route_table *t = NULL; - -  zvrf = zebra_vrf_lookup_by_id(vrfid); -  if (zvrf) -    switch (type) -      { -      case RNH_NEXTHOP_TYPE: -	t = zvrf->rnh_table[family2afi(family)]; -	break; -      case RNH_IMPORT_CHECK_TYPE: -	t = zvrf->import_check_table[family2afi(family)]; -	break; -      } - -  return t; +	struct zebra_vrf *zvrf; +	struct route_table *t = NULL; + +	zvrf = zebra_vrf_lookup_by_id(vrfid); +	if (zvrf) +		switch (type) { +		case RNH_NEXTHOP_TYPE: +			t = zvrf->rnh_table[family2afi(family)]; +			break; +		case RNH_IMPORT_CHECK_TYPE: +			t = zvrf->import_check_table[family2afi(family)]; +			break; +		} + +	return t;  } -char *rnh_str (struct rnh *rnh, char *buf, int size) +char *rnh_str(struct rnh *rnh, char *buf, int size)  { -  prefix2str(&(rnh->node->p), buf, size); -  return buf; +	prefix2str(&(rnh->node->p), buf, size); +	return buf;  } -struct rnh * -zebra_add_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) +struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)  { -  struct route_table *table; -  struct route_node *rn; -  struct rnh *rnh = NULL; -  char buf[PREFIX2STR_BUFFER]; - -  if (IS_ZEBRA_DEBUG_NHT) -    { -      prefix2str(p, buf, sizeof (buf)); -      zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); -    } -  table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); -  if (!table) -    { -      prefix2str(p, buf, sizeof (buf)); -      zlog_warn("%u: Add RNH %s type %d - table not found", -                vrfid, buf, type); -      return NULL; -    } - -  /* Make it sure prefixlen is applied to the prefix. */ -  apply_mask (p); - -  /* Lookup (or add) route node.*/ -  rn = route_node_get (table, p); - -  if (!rn->info) -    { -      rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh)); -      rnh->client_list = list_new(); -      rnh->vrf_id = vrfid; -      rnh->zebra_static_route_list = list_new(); -      route_lock_node (rn); -      rn->info = rnh; -      rnh->node = rn; -    } - -  route_unlock_node (rn); -  return (rn->info); +	struct route_table *table; +	struct route_node *rn; +	struct rnh *rnh = NULL; +	char buf[PREFIX2STR_BUFFER]; + +	if (IS_ZEBRA_DEBUG_NHT) { +		prefix2str(p, buf, sizeof(buf)); +		zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); +	} +	table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); +	if (!table) { +		prefix2str(p, buf, sizeof(buf)); +		zlog_warn("%u: Add RNH %s type %d - table not found", vrfid, +			  buf, type); +		return NULL; +	} + +	/* Make it sure prefixlen is applied to the prefix. */ +	apply_mask(p); + +	/* Lookup (or add) route node.*/ +	rn = route_node_get(table, p); + +	if (!rn->info) { +		rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh)); +		rnh->client_list = list_new(); +		rnh->vrf_id = vrfid; +		rnh->zebra_static_route_list = list_new(); +		route_lock_node(rn); +		rn->info = rnh; +		rnh->node = rn; +	} + +	route_unlock_node(rn); +	return (rn->info);  } -struct rnh * -zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) +struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)  { -  struct route_table *table; -  struct route_node *rn; +	struct route_table *table; +	struct route_node *rn; -  table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); -  if (!table) -    return NULL; +	table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); +	if (!table) +		return NULL; -  /* Make it sure prefixlen is applied to the prefix. */ -  apply_mask (p); +	/* Make it sure prefixlen is applied to the prefix. */ +	apply_mask(p); -  /* Lookup route node.*/ -  rn = route_node_lookup (table, p); -  if (!rn) -    return NULL; +	/* Lookup route node.*/ +	rn = route_node_lookup(table, p); +	if (!rn) +		return NULL; -  route_unlock_node (rn); -  return (rn->info); +	route_unlock_node(rn); +	return (rn->info);  } -void -zebra_free_rnh (struct rnh *rnh) +void zebra_free_rnh(struct rnh *rnh)  { -  rnh->flags |= ZEBRA_NHT_DELETED; -  list_free (rnh->client_list); -  list_free (rnh->zebra_static_route_list); -  free_state (rnh->vrf_id, rnh->state, rnh->node); -  XFREE (MTYPE_RNH, rnh); +	rnh->flags |= ZEBRA_NHT_DELETED; +	list_free(rnh->client_list); +	list_free(rnh->zebra_static_route_list); +	free_state(rnh->vrf_id, rnh->state, rnh->node); +	XFREE(MTYPE_RNH, rnh);  } -void -zebra_delete_rnh (struct rnh *rnh, rnh_type_t type) +void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)  { -  struct route_node *rn; +	struct route_node *rn; -  if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node)) -    return; +	if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node)) +		return; -  if (IS_ZEBRA_DEBUG_NHT) -    { -      char buf[PREFIX2STR_BUFFER]; -      zlog_debug("%u: Del RNH %s type %d", -                 rnh->vrf_id, rnh_str(rnh, buf, sizeof (buf)), type); -    } +	if (IS_ZEBRA_DEBUG_NHT) { +		char buf[PREFIX2STR_BUFFER]; +		zlog_debug("%u: Del RNH %s type %d", rnh->vrf_id, +			   rnh_str(rnh, buf, sizeof(buf)), type); +	} -  zebra_free_rnh (rnh); -  rn->info = NULL; -  route_unlock_node (rn); +	zebra_free_rnh(rnh); +	rn->info = NULL; +	route_unlock_node(rn);  } -void -zebra_add_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, -                      vrf_id_t vrf_id) +void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, +			  rnh_type_t type, vrf_id_t vrf_id)  { -  if (IS_ZEBRA_DEBUG_NHT) -    { -      char buf[PREFIX2STR_BUFFER]; -      zlog_debug("%u: Client %s registers for RNH %s type %d", -		 vrf_id, zebra_route_string(client->proto), -		 rnh_str(rnh, buf, sizeof (buf)), type); -    } -  if (!listnode_lookup(rnh->client_list, client)) -    { -      listnode_add(rnh->client_list, client); -      send_client(rnh, client, type, vrf_id); // Pending: check if its needed -    } +	if (IS_ZEBRA_DEBUG_NHT) { +		char buf[PREFIX2STR_BUFFER]; +		zlog_debug("%u: Client %s registers for RNH %s type %d", vrf_id, +			   zebra_route_string(client->proto), +			   rnh_str(rnh, buf, sizeof(buf)), type); +	} +	if (!listnode_lookup(rnh->client_list, client)) { +		listnode_add(rnh->client_list, client); +		send_client(rnh, client, type, +			    vrf_id); // Pending: check if its needed +	}  } -void -zebra_remove_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type) +void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, +			     rnh_type_t type)  { -  if (IS_ZEBRA_DEBUG_NHT) -    { -      char buf[PREFIX2STR_BUFFER]; -      zlog_debug("Client %s unregisters for RNH %s type %d", -		 zebra_route_string(client->proto), -		 rnh_str(rnh, buf, sizeof (buf)), type); -    } -  listnode_delete(rnh->client_list, client); -  if (list_isempty(rnh->client_list) && -      list_isempty(rnh->zebra_static_route_list)) -    zebra_delete_rnh(rnh, type); +	if (IS_ZEBRA_DEBUG_NHT) { +		char buf[PREFIX2STR_BUFFER]; +		zlog_debug("Client %s unregisters for RNH %s type %d", +			   zebra_route_string(client->proto), +			   rnh_str(rnh, buf, sizeof(buf)), type); +	} +	listnode_delete(rnh->client_list, client); +	if (list_isempty(rnh->client_list) +	    && list_isempty(rnh->zebra_static_route_list)) +		zebra_delete_rnh(rnh, type);  } -void -zebra_register_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, -                             struct route_node *static_rn) +void zebra_register_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, +				  struct route_node *static_rn)  { -  struct rnh *rnh; +	struct rnh *rnh; -  rnh = zebra_add_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); -  if (rnh && !listnode_lookup(rnh->zebra_static_route_list, static_rn)) -    { -      listnode_add(rnh->zebra_static_route_list, static_rn); -    } +	rnh = zebra_add_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); +	if (rnh && !listnode_lookup(rnh->zebra_static_route_list, static_rn)) { +		listnode_add(rnh->zebra_static_route_list, static_rn); +	}  } -void -zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, -                               struct route_node *static_rn) +void zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, +				    struct route_node *static_rn)  { -  struct rnh *rnh; +	struct rnh *rnh; -  rnh = zebra_lookup_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); -  if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED)) -    return; +	rnh = zebra_lookup_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); +	if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED)) +		return; -  listnode_delete(rnh->zebra_static_route_list, static_rn); +	listnode_delete(rnh->zebra_static_route_list, static_rn); -  if (list_isempty(rnh->client_list) && -      list_isempty(rnh->zebra_static_route_list)) -    zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); +	if (list_isempty(rnh->client_list) +	    && list_isempty(rnh->zebra_static_route_list)) +		zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);  } -void -zebra_deregister_rnh_static_nexthops (vrf_id_t vrf_id, struct nexthop *nexthop, -                                      struct route_node *rn) +void zebra_deregister_rnh_static_nexthops(vrf_id_t vrf_id, +					  struct nexthop *nexthop, +					  struct route_node *rn)  { -  struct nexthop *nh; -  struct prefix nh_p; - -  for (nh = nexthop; nh ; nh = nh->next) -    { -      switch (nh->type) -      { -        case NEXTHOP_TYPE_IPV4: -        case NEXTHOP_TYPE_IPV4_IFINDEX: -          nh_p.family = AF_INET; -          nh_p.prefixlen = IPV4_MAX_BITLEN; -          nh_p.u.prefix4 = nh->gate.ipv4; -          break; -        case NEXTHOP_TYPE_IPV6: -        case NEXTHOP_TYPE_IPV6_IFINDEX: -          nh_p.family = AF_INET6; -          nh_p.prefixlen = IPV6_MAX_BITLEN; -          nh_p.u.prefix6 = nh->gate.ipv6; -          break; -        /* -         * Not sure what really to do here, we are not -         * supposed to have either of these for NHT -         * and the code has no way to know what prefix -         * to use.  So I'm going to just continue -         * for the moment, which is preferable to -         * what is currently happening which is a -         * CRASH and BURN. -         * Some simple testing shows that we -         * are not leaving slag around for these -         * skipped static routes.  Since -         * they don't appear to be installed -         */ -        case NEXTHOP_TYPE_IFINDEX: -        case NEXTHOP_TYPE_BLACKHOLE: -          continue; -          break; -      } -      zebra_deregister_rnh_static_nh(vrf_id, &nh_p, rn); -    } +	struct nexthop *nh; +	struct prefix nh_p; + +	for (nh = nexthop; nh; nh = nh->next) { +		switch (nh->type) { +		case NEXTHOP_TYPE_IPV4: +		case NEXTHOP_TYPE_IPV4_IFINDEX: +			nh_p.family = AF_INET; +			nh_p.prefixlen = IPV4_MAX_BITLEN; +			nh_p.u.prefix4 = nh->gate.ipv4; +			break; +		case NEXTHOP_TYPE_IPV6: +		case NEXTHOP_TYPE_IPV6_IFINDEX: +			nh_p.family = AF_INET6; +			nh_p.prefixlen = IPV6_MAX_BITLEN; +			nh_p.u.prefix6 = nh->gate.ipv6; +			break; +		/* +		 * Not sure what really to do here, we are not +		 * supposed to have either of these for NHT +		 * and the code has no way to know what prefix +		 * to use.  So I'm going to just continue +		 * for the moment, which is preferable to +		 * what is currently happening which is a +		 * CRASH and BURN. +		 * Some simple testing shows that we +		 * are not leaving slag around for these +		 * skipped static routes.  Since +		 * they don't appear to be installed +		 */ +		case NEXTHOP_TYPE_IFINDEX: +		case NEXTHOP_TYPE_BLACKHOLE: +			continue; +			break; +		} +		zebra_deregister_rnh_static_nh(vrf_id, &nh_p, rn); +	}  }  /* Apply the NHT route-map for a client to the route (and nexthops)   * resolving a NH.   */ -static int -zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, -                         struct route_entry *re, int proto) +static int zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, +				    struct route_entry *re, int proto)  { -  int at_least_one = 0; -  int rmap_family;	       /* Route map has diff AF family enum */ -  struct nexthop *nexthop; -  int ret; - -  rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; - -  if (prn && re) -    { -      for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) -	{ -	  ret = zebra_nht_route_map_check(rmap_family, proto, &prn->p, re, -					  nexthop); -	  if (ret != RMAP_DENYMATCH) -	    { -	      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); -	      at_least_one++; /* at least one valid NH */ -	    } -	  else -	    { -	      UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); -	    } +	int at_least_one = 0; +	int rmap_family; /* Route map has diff AF family enum */ +	struct nexthop *nexthop; +	int ret; + +	rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; + +	if (prn && re) { +		for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { +			ret = zebra_nht_route_map_check(rmap_family, proto, +							&prn->p, re, nexthop); +			if (ret != RMAP_DENYMATCH) { +				SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); +				at_least_one++; /* at least one valid NH */ +			} else { +				UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); +			} +		}  	} -    } -  return (at_least_one); +	return (at_least_one);  }  /*   * Determine appropriate route (RE entry) resolving a tracked entry   * (nexthop or BGP route for import).   */ -static struct route_entry * -zebra_rnh_resolve_entry (vrf_id_t vrfid, int family, rnh_type_t type, -                         struct route_node *nrn, struct rnh *rnh, -                         struct route_node **prn) +static struct route_entry *zebra_rnh_resolve_entry(vrf_id_t vrfid, int family, +						   rnh_type_t type, +						   struct route_node *nrn, +						   struct rnh *rnh, +						   struct route_node **prn)  { -  struct route_table *route_table; -  struct route_node *rn; -  struct route_entry *re; - -  *prn = NULL; - -  route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); -  if (!route_table) // unexpected -    return NULL; - -  rn = route_node_match(route_table, &nrn->p); -  if (!rn) -    return NULL; - -  /* When resolving nexthops, do not resolve via the default route unless -   * 'ip nht resolve-via-default' is configured. -   */ -  if ((type == RNH_NEXTHOP_TYPE) && -      (is_default_prefix (&rn->p) && -      !nh_resolve_via_default(rn->p.family))) -    re = NULL; - else if ((type == RNH_IMPORT_CHECK_TYPE) && -          CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) && -          !prefix_same(&nrn->p, &rn->p)) -   re = NULL; -  else -    { -      /* Identify appropriate route entry. */ -      RNODE_FOREACH_RE(rn, re) -        { -          if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) -            continue; -          if (! CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) -            continue; - -          if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) -            { -              if (re->type == ZEBRA_ROUTE_CONNECT) -                break; -              if (re->type == ZEBRA_ROUTE_NHRP) -                { -                  struct nexthop *nexthop; -                  for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) -                    if (nexthop->type == NEXTHOP_TYPE_IFINDEX) -                      break; -                  if (nexthop) -                    break; -                } -            } -          else if ((type == RNH_IMPORT_CHECK_TYPE) && -                   (re->type == ZEBRA_ROUTE_BGP)) -            continue; -          else -            break; -        } -    } - -  /* Need to unlock route node */ -  route_unlock_node(rn); -  if (re) -    *prn = rn; -  return re; +	struct route_table *route_table; +	struct route_node *rn; +	struct route_entry *re; + +	*prn = NULL; + +	route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); +	if (!route_table) // unexpected +		return NULL; + +	rn = route_node_match(route_table, &nrn->p); +	if (!rn) +		return NULL; + +	/* When resolving nexthops, do not resolve via the default route unless +	 * 'ip nht resolve-via-default' is configured. +	 */ +	if ((type == RNH_NEXTHOP_TYPE) +	    && (is_default_prefix(&rn->p) +		&& !nh_resolve_via_default(rn->p.family))) +		re = NULL; +	else if ((type == RNH_IMPORT_CHECK_TYPE) +		 && CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) +		 && !prefix_same(&nrn->p, &rn->p)) +		re = NULL; +	else { +		/* Identify appropriate route entry. */ +		RNODE_FOREACH_RE(rn, re) +		{ +			if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) +				continue; +			if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) +				continue; + +			if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) { +				if (re->type == ZEBRA_ROUTE_CONNECT) +					break; +				if (re->type == ZEBRA_ROUTE_NHRP) { +					struct nexthop *nexthop; +					for (nexthop = re->nexthop; nexthop; +					     nexthop = nexthop->next) +						if (nexthop->type +						    == NEXTHOP_TYPE_IFINDEX) +							break; +					if (nexthop) +						break; +				} +			} else if ((type == RNH_IMPORT_CHECK_TYPE) +				   && (re->type == ZEBRA_ROUTE_BGP)) +				continue; +			else +				break; +		} +	} + +	/* Need to unlock route node */ +	route_unlock_node(rn); +	if (re) +		*prn = rn; +	return re;  }  /*   * See if a tracked route entry for import (by BGP) has undergone any   * change, and if so, notify the client.   */ -static void -zebra_rnh_eval_import_check_entry (vrf_id_t vrfid, int family, int force, -                                   struct route_node *nrn, struct rnh *rnh, -                                   struct route_entry *re) +static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, +					      int force, struct route_node *nrn, +					      struct rnh *rnh, +					      struct route_entry *re)  { -  int state_changed = 0; -  struct zserv *client; -  char bufn[INET6_ADDRSTRLEN]; -  struct listnode *node; -  struct nexthop *nexthop; - -  if (re && (rnh->state == NULL)) -    { -      for (ALL_NEXTHOPS(re->nexthop, nexthop)) -        if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) -          { -            state_changed = 1; -            break; -          } -    } -  else if (!re && (rnh->state != NULL)) -    state_changed = 1; - -  if (compare_state(re, rnh->state)) -    copy_state(rnh, re, nrn); - -  if (state_changed || force) -    { -      if (IS_ZEBRA_DEBUG_NHT) -        { -          prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); -          zlog_debug("%u:%s: Route import check %s %s\n", -                     vrfid, bufn, rnh->state ? "passed" : "failed", -                     state_changed ? "(state changed)" : ""); -        } -      /* state changed, notify clients */ -      for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) -        { -          send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid); -        } -    } +	int state_changed = 0; +	struct zserv *client; +	char bufn[INET6_ADDRSTRLEN]; +	struct listnode *node; +	struct nexthop *nexthop; + +	if (re && (rnh->state == NULL)) { +		for (ALL_NEXTHOPS(re->nexthop, nexthop)) +			if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { +				state_changed = 1; +				break; +			} +	} else if (!re && (rnh->state != NULL)) +		state_changed = 1; + +	if (compare_state(re, rnh->state)) +		copy_state(rnh, re, nrn); + +	if (state_changed || force) { +		if (IS_ZEBRA_DEBUG_NHT) { +			prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); +			zlog_debug("%u:%s: Route import check %s %s\n", vrfid, +				   bufn, rnh->state ? "passed" : "failed", +				   state_changed ? "(state changed)" : ""); +		} +		/* state changed, notify clients */ +		for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { +			send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid); +		} +	}  }  /*   * Notify clients registered for this nexthop about a change.   */ -static void -zebra_rnh_notify_protocol_clients (vrf_id_t vrfid, int family, -                                   struct route_node *nrn, struct rnh *rnh, -                                   struct route_node *prn, struct route_entry *re) +static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, +					      struct route_node *nrn, +					      struct rnh *rnh, +					      struct route_node *prn, +					      struct route_entry *re)  { -  struct listnode *node; -  struct zserv *client; -  char bufn[INET6_ADDRSTRLEN]; -  char bufp[INET6_ADDRSTRLEN]; -  int num_resolving_nh; - -  if (IS_ZEBRA_DEBUG_NHT) -    { -      prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); -      if (prn && re) -        { -          prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); -          zlog_debug("%u:%s: NH resolved over route %s", vrfid, bufn, bufp); -        } -      else -        zlog_debug("%u:%s: NH has become unresolved", vrfid, bufn); -    } - -  for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) -    { -      if (prn && re) -        { -          /* Apply route-map for this client to route resolving this -           * nexthop to see if it is filtered or not. -           */ -          num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, -                                                      client->proto); -          if (num_resolving_nh) -            rnh->filtered[client->proto] = 0; -          else -            rnh->filtered[client->proto] = 1; - -          if (IS_ZEBRA_DEBUG_NHT) -            zlog_debug("%u:%s: Notifying client %s about NH %s", -                       vrfid, bufn, zebra_route_string(client->proto), -                       num_resolving_nh ? "" : "(filtered by route-map)"); -        } -      else -        { -          rnh->filtered[client->proto] = 0; -          if (IS_ZEBRA_DEBUG_NHT) -            zlog_debug("%u:%s: Notifying client %s about NH (unreachable)", -                       vrfid, bufn, zebra_route_string(client->proto)); -        } - -      send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid); -    } +	struct listnode *node; +	struct zserv *client; +	char bufn[INET6_ADDRSTRLEN]; +	char bufp[INET6_ADDRSTRLEN]; +	int num_resolving_nh; + +	if (IS_ZEBRA_DEBUG_NHT) { +		prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); +		if (prn && re) { +			prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); +			zlog_debug("%u:%s: NH resolved over route %s", vrfid, +				   bufn, bufp); +		} else +			zlog_debug("%u:%s: NH has become unresolved", vrfid, +				   bufn); +	} + +	for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { +		if (prn && re) { +			/* Apply route-map for this client to route resolving +			 * this +			 * nexthop to see if it is filtered or not. +			 */ +			num_resolving_nh = zebra_rnh_apply_nht_rmap( +				family, prn, re, client->proto); +			if (num_resolving_nh) +				rnh->filtered[client->proto] = 0; +			else +				rnh->filtered[client->proto] = 1; + +			if (IS_ZEBRA_DEBUG_NHT) +				zlog_debug( +					"%u:%s: Notifying client %s about NH %s", +					vrfid, bufn, +					zebra_route_string(client->proto), +					num_resolving_nh +						? "" +						: "(filtered by route-map)"); +		} else { +			rnh->filtered[client->proto] = 0; +			if (IS_ZEBRA_DEBUG_NHT) +				zlog_debug( +					"%u:%s: Notifying client %s about NH (unreachable)", +					vrfid, bufn, +					zebra_route_string(client->proto)); +		} + +		send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid); +	}  } -static void -zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, -                                 struct route_node *nrn, struct rnh *rnh, -                                 struct route_node *prn, struct route_entry *re) +static void zebra_rnh_process_static_routes(vrf_id_t vrfid, int family, +					    struct route_node *nrn, +					    struct rnh *rnh, +					    struct route_node *prn, +					    struct route_entry *re)  { -  struct listnode *node; -  int num_resolving_nh = 0; -  struct route_node *static_rn; -  struct route_entry *sre; -  struct nexthop *nexthop; -  char bufn[INET6_ADDRSTRLEN]; -  char bufp[INET6_ADDRSTRLEN]; -  char bufs[INET6_ADDRSTRLEN]; - -  if (IS_ZEBRA_DEBUG_NHT) -    { -      prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); -      if (prn) -        prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); -    } - -  if (prn && re) -    { -      /* Apply route-map for "static" to route resolving this -       * nexthop to see if it is filtered or not. -       */ -      num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, -                                                  ZEBRA_ROUTE_STATIC); -      if (num_resolving_nh) -        rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; -      else -        rnh->filtered[ZEBRA_ROUTE_STATIC] = 1; -    } -  else -    rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; - -  /* Evaluate each static route associated with this nexthop. */ -  for (ALL_LIST_ELEMENTS_RO(rnh->zebra_static_route_list, node, -                            static_rn)) -    { -      RNODE_FOREACH_RE(static_rn, sre) -        { -          if (sre->type != ZEBRA_ROUTE_STATIC) -            continue; - -	  /* Set the filter flag for the correct nexthop - static route may -	   * be having multiple. We care here only about registered nexthops. -	   */ -	  for (nexthop = sre->nexthop; nexthop; nexthop = nexthop->next) -	    { -	      switch (nexthop->type) -		{ -		case NEXTHOP_TYPE_IPV4: -		case NEXTHOP_TYPE_IPV4_IFINDEX: -		  if (nexthop->gate.ipv4.s_addr == nrn->p.u.prefix4.s_addr) -		    { -		      if (num_resolving_nh) -			UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); -		      else -			SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); -		    } -		  break; -		case NEXTHOP_TYPE_IPV6: -		case NEXTHOP_TYPE_IPV6_IFINDEX: +	struct listnode *node; +	int num_resolving_nh = 0; +	struct route_node *static_rn; +	struct route_entry *sre; +	struct nexthop *nexthop; +	char bufn[INET6_ADDRSTRLEN]; +	char bufp[INET6_ADDRSTRLEN]; +	char bufs[INET6_ADDRSTRLEN]; + +	if (IS_ZEBRA_DEBUG_NHT) { +		prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); +		if (prn) +			prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); +	} -              if (memcmp(&nexthop->gate.ipv6,&nrn->p.u.prefix6, 16) == 0) -                { -                  if (num_resolving_nh) -                    UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); -                  else -                    SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); -                } -              break; -            default: -              break; -            } -        } - -	  if (IS_ZEBRA_DEBUG_NHT) -	    { -	      prefix2str(&static_rn->p, bufs, INET6_ADDRSTRLEN); -	      if (prn && re) -		zlog_debug("%u:%s: NH change %s, scheduling static route %s", -			   vrfid, bufn, num_resolving_nh ? -			   "" : "(filtered by route-map)", bufs); -	      else -		zlog_debug("%u:%s: NH unreachable, scheduling static route %s", -			   vrfid, bufn, bufs); -	    } - -          SET_FLAG(sre->status, ROUTE_ENTRY_CHANGED); -          SET_FLAG(sre->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); -        } - -      rib_queue_add(static_rn); -    } +	if (prn && re) { +		/* Apply route-map for "static" to route resolving this +		 * nexthop to see if it is filtered or not. +		 */ +		num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, +							    ZEBRA_ROUTE_STATIC); +		if (num_resolving_nh) +			rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; +		else +			rnh->filtered[ZEBRA_ROUTE_STATIC] = 1; +	} else +		rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; + +	/* Evaluate each static route associated with this nexthop. */ +	for (ALL_LIST_ELEMENTS_RO(rnh->zebra_static_route_list, node, +				  static_rn)) { +		RNODE_FOREACH_RE(static_rn, sre) +		{ +			if (sre->type != ZEBRA_ROUTE_STATIC) +				continue; + +			/* Set the filter flag for the correct nexthop - static +			 * route may +			 * be having multiple. We care here only about +			 * registered nexthops. +			 */ +			for (nexthop = sre->nexthop; nexthop; +			     nexthop = nexthop->next) { +				switch (nexthop->type) { +				case NEXTHOP_TYPE_IPV4: +				case NEXTHOP_TYPE_IPV4_IFINDEX: +					if (nexthop->gate.ipv4.s_addr +					    == nrn->p.u.prefix4.s_addr) { +						if (num_resolving_nh) +							UNSET_FLAG( +								nexthop->flags, +								NEXTHOP_FLAG_FILTERED); +						else +							SET_FLAG( +								nexthop->flags, +								NEXTHOP_FLAG_FILTERED); +					} +					break; +				case NEXTHOP_TYPE_IPV6: +				case NEXTHOP_TYPE_IPV6_IFINDEX: + +					if (memcmp(&nexthop->gate.ipv6, +						   &nrn->p.u.prefix6, 16) +					    == 0) { +						if (num_resolving_nh) +							UNSET_FLAG( +								nexthop->flags, +								NEXTHOP_FLAG_FILTERED); +						else +							SET_FLAG( +								nexthop->flags, +								NEXTHOP_FLAG_FILTERED); +					} +					break; +				default: +					break; +				} +			} + +			if (IS_ZEBRA_DEBUG_NHT) { +				prefix2str(&static_rn->p, bufs, +					   INET6_ADDRSTRLEN); +				if (prn && re) +					zlog_debug( +						"%u:%s: NH change %s, scheduling static route %s", +						vrfid, bufn, +						num_resolving_nh +							? "" +							: "(filtered by route-map)", +						bufs); +				else +					zlog_debug( +						"%u:%s: NH unreachable, scheduling static route %s", +						vrfid, bufn, bufs); +			} + +			SET_FLAG(sre->status, ROUTE_ENTRY_CHANGED); +			SET_FLAG(sre->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); +		} + +		rib_queue_add(static_rn); +	}  }  /* @@ -614,83 +600,78 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family,   * take appropriate action; this involves notifying any clients and/or   * scheduling dependent static routes for processing.   */ -static void -zebra_rnh_eval_nexthop_entry (vrf_id_t vrfid, int family, int force, -                              struct route_node *nrn, struct rnh *rnh, -                              struct route_node *prn, struct route_entry *re) +static void zebra_rnh_eval_nexthop_entry(vrf_id_t vrfid, int family, int force, +					 struct route_node *nrn, +					 struct rnh *rnh, +					 struct route_node *prn, +					 struct route_entry *re)  { -  int state_changed = 0; - -  /* If we're resolving over a different route, resolution has changed or -   * the resolving route has some change (e.g., metric), there is a state -   * change. -   */ -  if (!prefix_same(&rnh->resolved_route, &prn->p)) -    { -      if (prn) -        prefix_copy(&rnh->resolved_route, &prn->p); -      else -        memset(&rnh->resolved_route, 0, sizeof(struct prefix)); - -      copy_state(rnh, re, nrn); -      state_changed = 1; -    } -  else if (compare_state(re, rnh->state)) -    { -      copy_state(rnh, re, nrn); -      state_changed = 1; -    } - -  if (state_changed || force) -    { -      /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e., -       * rnh->state. -       */ -      /* Notify registered protocol clients. */ -      zebra_rnh_notify_protocol_clients (vrfid, family, nrn, rnh, -                                         prn, rnh->state); - -      /* Process static routes attached to this nexthop */ -      zebra_rnh_process_static_routes (vrfid, family, nrn, rnh, -                                       prn, rnh->state); -    } +	int state_changed = 0; + +	/* If we're resolving over a different route, resolution has changed or +	 * the resolving route has some change (e.g., metric), there is a state +	 * change. +	 */ +	if (!prefix_same(&rnh->resolved_route, &prn->p)) { +		if (prn) +			prefix_copy(&rnh->resolved_route, &prn->p); +		else +			memset(&rnh->resolved_route, 0, sizeof(struct prefix)); + +		copy_state(rnh, re, nrn); +		state_changed = 1; +	} else if (compare_state(re, rnh->state)) { +		copy_state(rnh, re, nrn); +		state_changed = 1; +	} + +	if (state_changed || force) { +		/* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e., +		 * rnh->state. +		 */ +		/* Notify registered protocol clients. */ +		zebra_rnh_notify_protocol_clients(vrfid, family, nrn, rnh, prn, +						  rnh->state); + +		/* Process static routes attached to this nexthop */ +		zebra_rnh_process_static_routes(vrfid, family, nrn, rnh, prn, +						rnh->state); +	}  }  /* Evaluate one tracked entry */ -static void -zebra_rnh_evaluate_entry (vrf_id_t vrfid, int family, int force, rnh_type_t type, -                          struct route_node *nrn) +static void zebra_rnh_evaluate_entry(vrf_id_t vrfid, int family, int force, +				     rnh_type_t type, struct route_node *nrn)  { -  struct rnh *rnh; -  struct route_entry *re; -  struct route_node *prn; -  char bufn[INET6_ADDRSTRLEN]; - -  if (IS_ZEBRA_DEBUG_NHT) -    { -      prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); -      zlog_debug("%u:%s: Evaluate RNH, type %d %s", -                 vrfid, bufn, type, force ? "(force)" : ""); -    } - -  rnh = nrn->info; - -  /* Identify route entry (RE) resolving this tracked entry. */ -  re = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn); - -  /* If the entry cannot be resolved and that is also the existing state, -   * there is nothing further to do. -   */ -  if (!re && rnh->state == NULL && !force) -    return; - -  /* Process based on type of entry. */ -  if (type == RNH_IMPORT_CHECK_TYPE) -    zebra_rnh_eval_import_check_entry (vrfid, family, force, -                                       nrn, rnh, re); -  else -    zebra_rnh_eval_nexthop_entry (vrfid, family, force, -                                  nrn, rnh, prn, re); +	struct rnh *rnh; +	struct route_entry *re; +	struct route_node *prn; +	char bufn[INET6_ADDRSTRLEN]; + +	if (IS_ZEBRA_DEBUG_NHT) { +		prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); +		zlog_debug("%u:%s: Evaluate RNH, type %d %s", vrfid, bufn, type, +			   force ? "(force)" : ""); +	} + +	rnh = nrn->info; + +	/* Identify route entry (RE) resolving this tracked entry. */ +	re = zebra_rnh_resolve_entry(vrfid, family, type, nrn, rnh, &prn); + +	/* If the entry cannot be resolved and that is also the existing state, +	 * there is nothing further to do. +	 */ +	if (!re && rnh->state == NULL && !force) +		return; + +	/* Process based on type of entry. */ +	if (type == RNH_IMPORT_CHECK_TYPE) +		zebra_rnh_eval_import_check_entry(vrfid, family, force, nrn, +						  rnh, re); +	else +		zebra_rnh_eval_nexthop_entry(vrfid, family, force, nrn, rnh, +					     prn, re);  }  /* @@ -702,328 +683,321 @@ zebra_rnh_evaluate_entry (vrf_id_t vrfid, int family, int force, rnh_type_t type   * we can have a situation where one re entry   * covers multiple nexthops we are interested in.   */ -static void -zebra_rnh_clear_nhc_flag (vrf_id_t vrfid, int family, rnh_type_t type, -                          struct route_node *nrn) +static void zebra_rnh_clear_nhc_flag(vrf_id_t vrfid, int family, +				     rnh_type_t type, struct route_node *nrn)  { -  struct rnh *rnh; -  struct route_entry *re; -  struct route_node *prn; +	struct rnh *rnh; +	struct route_entry *re; +	struct route_node *prn; -  rnh = nrn->info; +	rnh = nrn->info; -  re = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn); +	re = zebra_rnh_resolve_entry(vrfid, family, type, nrn, rnh, &prn); -  if (re) -    UNSET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); +	if (re) +		UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED);  }  /* Evaluate all tracked entries (nexthops or routes for import into BGP)   * of a particular VRF and address-family or a specific prefix.   */ -void -zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type, -                    struct prefix *p) +void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, +			struct prefix *p)  { -  struct route_table *rnh_table; -  struct route_node *nrn; - -  rnh_table = get_rnh_table(vrfid, family, type); -  if (!rnh_table) // unexpected -    return; - -  if (p) -    { -      /* Evaluating a specific entry, make sure it exists. */ -      nrn = route_node_lookup (rnh_table, p); -      if (nrn && nrn->info) -        zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn); - -      if (nrn) -        route_unlock_node (nrn); -    } -  else -    { -      /* Evaluate entire table. */ -      nrn = route_top (rnh_table); -      while (nrn) -        { -          if (nrn->info) -            zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn); -          nrn = route_next(nrn); /* this will also unlock nrn */ -        } -      nrn = route_top (rnh_table); -      while (nrn) -        { -          if (nrn->info) -            zebra_rnh_clear_nhc_flag (vrfid, family, type, nrn); -          nrn = route_next(nrn); /* this will also unlock nrn */ -        } -    } +	struct route_table *rnh_table; +	struct route_node *nrn; + +	rnh_table = get_rnh_table(vrfid, family, type); +	if (!rnh_table) // unexpected +		return; + +	if (p) { +		/* Evaluating a specific entry, make sure it exists. */ +		nrn = route_node_lookup(rnh_table, p); +		if (nrn && nrn->info) +			zebra_rnh_evaluate_entry(vrfid, family, force, type, +						 nrn); + +		if (nrn) +			route_unlock_node(nrn); +	} else { +		/* Evaluate entire table. */ +		nrn = route_top(rnh_table); +		while (nrn) { +			if (nrn->info) +				zebra_rnh_evaluate_entry(vrfid, family, force, +							 type, nrn); +			nrn = route_next(nrn); /* this will also unlock nrn */ +		} +		nrn = route_top(rnh_table); +		while (nrn) { +			if (nrn->info) +				zebra_rnh_clear_nhc_flag(vrfid, family, type, +							 nrn); +			nrn = route_next(nrn); /* this will also unlock nrn */ +		} +	}  } -void -zebra_print_rnh_table (vrf_id_t vrfid, int af, struct vty *vty, rnh_type_t type) +void zebra_print_rnh_table(vrf_id_t vrfid, int af, struct vty *vty, +			   rnh_type_t type)  { -  struct route_table *table; -  struct route_node *rn; - -  table = get_rnh_table(vrfid, af, type); -  if (!table) -    { -      zlog_debug("print_rnhs: rnh table not found\n"); -      return; -    } - -  for (rn = route_top(table); rn; rn = route_next(rn)) -      if (rn->info) -	print_rnh(rn, vty); +	struct route_table *table; +	struct route_node *rn; + +	table = get_rnh_table(vrfid, af, type); +	if (!table) { +		zlog_debug("print_rnhs: rnh table not found\n"); +		return; +	} + +	for (rn = route_top(table); rn; rn = route_next(rn)) +		if (rn->info) +			print_rnh(rn, vty);  } -int -zebra_cleanup_rnh_client (vrf_id_t vrf_id, int family, struct zserv *client, -			  rnh_type_t type) +int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, struct zserv *client, +			     rnh_type_t type)  { -  struct route_table *ntable; -  struct route_node *nrn; -  struct rnh *rnh; - -  if (IS_ZEBRA_DEBUG_NHT) -    zlog_debug("%u: Client %s RNH cleanup for family %d type %d", -               vrf_id, zebra_route_string(client->proto), family, type); - -  ntable = get_rnh_table(vrf_id, family, type); -  if (!ntable) -    { -      zlog_debug("cleanup_rnh_client: rnh table not found\n"); -      return -1; -    } - -  for (nrn = route_top (ntable); nrn; nrn = route_next (nrn)) -    { -      if (!nrn->info) -	  continue; - -      rnh = nrn->info; -      zebra_remove_rnh_client(rnh, client, type); -    } -  return 1; +	struct route_table *ntable; +	struct route_node *nrn; +	struct rnh *rnh; + +	if (IS_ZEBRA_DEBUG_NHT) +		zlog_debug("%u: Client %s RNH cleanup for family %d type %d", +			   vrf_id, zebra_route_string(client->proto), family, +			   type); + +	ntable = get_rnh_table(vrf_id, family, type); +	if (!ntable) { +		zlog_debug("cleanup_rnh_client: rnh table not found\n"); +		return -1; +	} + +	for (nrn = route_top(ntable); nrn; nrn = route_next(nrn)) { +		if (!nrn->info) +			continue; + +		rnh = nrn->info; +		zebra_remove_rnh_client(rnh, client, type); +	} +	return 1;  }  /**   * free_state - free up the re structure associated with the rnh.   */ -static void -free_state (vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn) +static void free_state(vrf_id_t vrf_id, struct route_entry *re, +		       struct route_node *rn)  { -  if (!re) -    return; +	if (!re) +		return; -  /* free RE and nexthops */ -  zebra_deregister_rnh_static_nexthops (vrf_id, re->nexthop, rn); -  nexthops_free(re->nexthop); -  XFREE (MTYPE_RE, re); +	/* free RE and nexthops */ +	zebra_deregister_rnh_static_nexthops(vrf_id, re->nexthop, rn); +	nexthops_free(re->nexthop); +	XFREE(MTYPE_RE, re);  } -static void -copy_state (struct rnh *rnh, struct route_entry *re, struct route_node *rn) +static void copy_state(struct rnh *rnh, struct route_entry *re, +		       struct route_node *rn)  { -  struct route_entry *state; +	struct route_entry *state; -  if (rnh->state) -    { -      free_state(rnh->vrf_id, rnh->state, rn); -      rnh->state = NULL; -    } +	if (rnh->state) { +		free_state(rnh->vrf_id, rnh->state, rn); +		rnh->state = NULL; +	} -  if (!re) -    return; +	if (!re) +		return; -  state = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); -  state->type = re->type; -  state->metric = re->metric; +	state = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); +	state->type = re->type; +	state->metric = re->metric; -  route_entry_copy_nexthops(state, re->nexthop); -  rnh->state = state; +	route_entry_copy_nexthops(state, re->nexthop); +	rnh->state = state;  } -static int -compare_state (struct route_entry *r1, struct route_entry *r2) +static int compare_state(struct route_entry *r1, struct route_entry *r2)  { -  if (!r1 && !r2) -    return 0; +	if (!r1 && !r2) +		return 0; -  if ((!r1 && r2) || (r1 && !r2)) -      return 1; +	if ((!r1 && r2) || (r1 && !r2)) +		return 1; -  if (r1->metric != r2->metric) -      return 1; +	if (r1->metric != r2->metric) +		return 1; -  if (r1->nexthop_num != r2->nexthop_num) -      return 1; +	if (r1->nexthop_num != r2->nexthop_num) +		return 1; -  if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)) -    return 1; +	if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)) +		return 1; -  return 0; +	return 0;  } -static int -send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id) +static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, +		       vrf_id_t vrf_id)  { -  struct stream *s; -  struct route_entry *re; -  unsigned long nump; -  u_char num; -  struct nexthop *nexthop; -  struct route_node *rn; -  int cmd = (type == RNH_IMPORT_CHECK_TYPE) -    ? ZEBRA_IMPORT_CHECK_UPDATE : ZEBRA_NEXTHOP_UPDATE; - -  rn = rnh->node; -  re = rnh->state; - -  /* Get output stream. */ -  s = client->obuf; -  stream_reset (s); - -  zserv_create_header (s, cmd, vrf_id); - -  stream_putw(s, rn->p.family); -  switch (rn->p.family) -    { -    case AF_INET: -      stream_putc(s, rn->p.prefixlen); -      stream_put_in_addr(s, &rn->p.u.prefix4); -      break; -    case AF_INET6: -      stream_putc(s, rn->p.prefixlen); -      stream_put(s, &rn->p.u.prefix6, IPV6_MAX_BYTELEN); -      break; -    default: -      zlog_err("%s: Unknown family (%d) notification attempted\n", -	       __FUNCTION__, rn->p.family); -      break; -    } -  if (re) -    { -      stream_putc (s, re->distance); -      stream_putl (s, re->metric); -      num = 0; -      nump = stream_get_endp(s); -      stream_putc (s, 0); -      for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) -	if ((CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) || -             CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) && -	    CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) -	  { -	    stream_putc (s, nexthop->type); -	    switch (nexthop->type) -	      { -	      case NEXTHOP_TYPE_IPV4: -		stream_put_in_addr (s, &nexthop->gate.ipv4); -                stream_putl (s, nexthop->ifindex); +	struct stream *s; +	struct route_entry *re; +	unsigned long nump; +	u_char num; +	struct nexthop *nexthop; +	struct route_node *rn; +	int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE +						  : ZEBRA_NEXTHOP_UPDATE; + +	rn = rnh->node; +	re = rnh->state; + +	/* Get output stream. */ +	s = client->obuf; +	stream_reset(s); + +	zserv_create_header(s, cmd, vrf_id); + +	stream_putw(s, rn->p.family); +	switch (rn->p.family) { +	case AF_INET: +		stream_putc(s, rn->p.prefixlen); +		stream_put_in_addr(s, &rn->p.u.prefix4);  		break; -	      case NEXTHOP_TYPE_IFINDEX: -		stream_putl (s, nexthop->ifindex); +	case AF_INET6: +		stream_putc(s, rn->p.prefixlen); +		stream_put(s, &rn->p.u.prefix6, IPV6_MAX_BYTELEN);  		break; -	      case NEXTHOP_TYPE_IPV4_IFINDEX: -		stream_put_in_addr (s, &nexthop->gate.ipv4); -		stream_putl (s, nexthop->ifindex); +	default: +		zlog_err("%s: Unknown family (%d) notification attempted\n", +			 __FUNCTION__, rn->p.family);  		break; -	      case NEXTHOP_TYPE_IPV6: -		stream_put (s, &nexthop->gate.ipv6, 16); -                stream_putl (s, nexthop->ifindex); -		break; -	      case NEXTHOP_TYPE_IPV6_IFINDEX: -		stream_put (s, &nexthop->gate.ipv6, 16); -		stream_putl (s, nexthop->ifindex); -		break; -	      default: -                /* do nothing */ -		break; -	      } -	    num++; -	  } -      stream_putc_at (s, nump, num); -    } -  else -    { -      stream_putc (s, 0);  // distance -      stream_putl (s, 0);  // metric -      stream_putc (s, 0);  // nexthops -    } -  stream_putw_at (s, 0, stream_get_endp (s)); - -  client->nh_last_upd_time = monotime(NULL); -  client->last_write_cmd = cmd; -  return zebra_server_send_message(client); +	} +	if (re) { +		stream_putc(s, re->distance); +		stream_putl(s, re->metric); +		num = 0; +		nump = stream_get_endp(s); +		stream_putc(s, 0); +		for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) +			if ((CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) +			     || CHECK_FLAG(nexthop->flags, +					   NEXTHOP_FLAG_RECURSIVE)) +			    && CHECK_FLAG(nexthop->flags, +					  NEXTHOP_FLAG_ACTIVE)) { +				stream_putc(s, nexthop->type); +				switch (nexthop->type) { +				case NEXTHOP_TYPE_IPV4: +					stream_put_in_addr(s, +							   &nexthop->gate.ipv4); +					stream_putl(s, nexthop->ifindex); +					break; +				case NEXTHOP_TYPE_IFINDEX: +					stream_putl(s, nexthop->ifindex); +					break; +				case NEXTHOP_TYPE_IPV4_IFINDEX: +					stream_put_in_addr(s, +							   &nexthop->gate.ipv4); +					stream_putl(s, nexthop->ifindex); +					break; +				case NEXTHOP_TYPE_IPV6: +					stream_put(s, &nexthop->gate.ipv6, 16); +					stream_putl(s, nexthop->ifindex); +					break; +				case NEXTHOP_TYPE_IPV6_IFINDEX: +					stream_put(s, &nexthop->gate.ipv6, 16); +					stream_putl(s, nexthop->ifindex); +					break; +				default: +					/* do nothing */ +					break; +				} +				num++; +			} +		stream_putc_at(s, nump, num); +	} else { +		stream_putc(s, 0); // distance +		stream_putl(s, 0); // metric +		stream_putc(s, 0); // nexthops +	} +	stream_putw_at(s, 0, stream_get_endp(s)); + +	client->nh_last_upd_time = monotime(NULL); +	client->last_write_cmd = cmd; +	return zebra_server_send_message(client);  } -static void -print_nh (struct nexthop *nexthop, struct vty *vty) +static void print_nh(struct nexthop *nexthop, struct vty *vty)  { -  char buf[BUFSIZ]; -  struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - -  switch (nexthop->type) -    { -    case NEXTHOP_TYPE_IPV4: -    case NEXTHOP_TYPE_IPV4_IFINDEX: -      vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); -      if (nexthop->ifindex) -	vty_out (vty, ", %s", ifindex2ifname_per_ns (zns, nexthop->ifindex)); -      break; -    case NEXTHOP_TYPE_IPV6: -    case NEXTHOP_TYPE_IPV6_IFINDEX: -      vty_out (vty, " %s", -	       inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); -      if (nexthop->ifindex) -	vty_out (vty, ", via %s", ifindex2ifname_per_ns (zns, nexthop->ifindex)); -      break; -    case NEXTHOP_TYPE_IFINDEX: -      vty_out (vty, " is directly connected, %s", -	       ifindex2ifname_per_ns (zns, nexthop->ifindex)); -      break; -    case NEXTHOP_TYPE_BLACKHOLE: -      vty_out (vty, " is directly connected, Null0"); -      break; -    default: -      break; -    } -  vty_out(vty, "\n"); +	char buf[BUFSIZ]; +	struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + +	switch (nexthop->type) { +	case NEXTHOP_TYPE_IPV4: +	case NEXTHOP_TYPE_IPV4_IFINDEX: +		vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); +		if (nexthop->ifindex) +			vty_out(vty, ", %s", +				ifindex2ifname_per_ns(zns, nexthop->ifindex)); +		break; +	case NEXTHOP_TYPE_IPV6: +	case NEXTHOP_TYPE_IPV6_IFINDEX: +		vty_out(vty, " %s", +			inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); +		if (nexthop->ifindex) +			vty_out(vty, ", via %s", +				ifindex2ifname_per_ns(zns, nexthop->ifindex)); +		break; +	case NEXTHOP_TYPE_IFINDEX: +		vty_out(vty, " is directly connected, %s", +			ifindex2ifname_per_ns(zns, nexthop->ifindex)); +		break; +	case NEXTHOP_TYPE_BLACKHOLE: +		vty_out(vty, " is directly connected, Null0"); +		break; +	default: +		break; +	} +	vty_out(vty, "\n");  } -static void -print_rnh (struct route_node *rn, struct vty *vty) +static void print_rnh(struct route_node *rn, struct vty *vty)  { -  struct rnh *rnh; -  struct nexthop *nexthop; -  struct listnode *node; -  struct zserv *client; -  char buf[BUFSIZ]; - -  rnh = rn->info; -  vty_out(vty, "%s%s\n", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), -	  CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : ""); -  if (rnh->state) -    { -      vty_out(vty, " resolved via %s\n", -	      zebra_route_string(rnh->state->type)); -      for (nexthop = rnh->state->nexthop; nexthop; nexthop = nexthop->next) -	print_nh(nexthop, vty); -    } -  else -    vty_out(vty, " unresolved%s\n", -	    CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : ""); - -  vty_out(vty, " Client list:"); -  for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) -    vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto), -	    client->sock, rnh->filtered[client->proto] ? "(filtered)" : ""); -  if (!list_isempty(rnh->zebra_static_route_list)) -    vty_out(vty, " zebra%s", rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : ""); -  vty_out(vty, "\n"); +	struct rnh *rnh; +	struct nexthop *nexthop; +	struct listnode *node; +	struct zserv *client; +	char buf[BUFSIZ]; + +	rnh = rn->info; +	vty_out(vty, "%s%s\n", +		inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), +		CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" +							    : ""); +	if (rnh->state) { +		vty_out(vty, " resolved via %s\n", +			zebra_route_string(rnh->state->type)); +		for (nexthop = rnh->state->nexthop; nexthop; +		     nexthop = nexthop->next) +			print_nh(nexthop, vty); +	} else +		vty_out(vty, " unresolved%s\n", +			CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) +				? "(Connected)" +				: ""); + +	vty_out(vty, " Client list:"); +	for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) +		vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto), +			client->sock, +			rnh->filtered[client->proto] ? "(filtered)" : ""); +	if (!list_isempty(rnh->zebra_static_route_list)) +		vty_out(vty, " zebra%s", +			rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : ""); +	vty_out(vty, "\n");  }  | 
