Esempio n. 1
0
void nhrp_interface_update(struct interface *ifp)
{
	struct nhrp_interface *nifp = ifp->info;
	struct nhrp_afi_data *if_ad;
	afi_t afi;
	int enabled = 0;

	notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_CHANGED);

	for (afi = 0; afi < AFI_MAX; afi++) {
		if_ad = &nifp->afi[afi];

		if (sockunion_family(&nifp->nbma) == AF_UNSPEC ||
		    ifp->ifindex == IFINDEX_INTERNAL || !if_is_up(ifp) ||
		    !if_ad->network_id) {
			if (if_ad->configured) {
				if_ad->configured = 0;
				nhrp_interface_update_address(ifp, afi, 1);
			}
			continue;
		}

		if (!if_ad->configured) {
			os_configure_dmvpn(ifp->ifindex, ifp->name, afi2family(afi));
			if_ad->configured = 1;
			nhrp_interface_update_address(ifp, afi, 1);
		}

		enabled = 1;
	}

	if (enabled != nifp->enabled) {
		nifp->enabled = enabled;
		notifier_call(&nifp->notifier_list, enabled ? NOTIFY_INTERFACE_UP : NOTIFY_INTERFACE_DOWN);
	}
}
Esempio n. 2
0
static void nhrp_interface_update_address(struct interface *ifp, afi_t afi, int force)
{
	const int family = afi2family(afi);
	struct nhrp_interface *nifp = ifp->info;
	struct nhrp_afi_data *if_ad = &nifp->afi[afi];
	struct nhrp_cache *nc;
	struct connected *c, *best;
	struct listnode *cnode;
	union sockunion addr;
	char buf[PREFIX_STRLEN];

	/* Select new best match preferring primary address */
	best = NULL;
	for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
		if (PREFIX_FAMILY(c->address) != family)
			continue;
		if (best == NULL) {
			best = c;
			continue;
		}
		if ((best->flags & ZEBRA_IFA_SECONDARY) && !(c->flags & ZEBRA_IFA_SECONDARY)) {
			best = c;
			continue;
		}
		if (!(best->flags & ZEBRA_IFA_SECONDARY) && (c->flags & ZEBRA_IFA_SECONDARY))
			continue;
		if (best->address->prefixlen > c->address->prefixlen) {
			best = c;
			continue;
		}
		if (best->address->prefixlen < c->address->prefixlen)
			continue;
	}

	/* On NHRP interfaces a host prefix is required */
	if (best && if_ad->configured && best->address->prefixlen != 8 * prefix_blen(best->address)) {
		zlog_notice("%s: %s is not a host prefix", ifp->name,
			prefix2str(best->address, buf, sizeof buf));
		best = NULL;
	}

	/* Update address if it changed */
	if (best)
		prefix2sockunion(best->address, &addr);
	else
		memset(&addr, 0, sizeof(addr));

	if (!force && sockunion_same(&if_ad->addr, &addr))
		return;

	if (sockunion_family(&if_ad->addr) != AF_UNSPEC) {
		nc = nhrp_cache_get(ifp, &if_ad->addr, 0);
		if (nc) nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, -1, NULL, 0, NULL);
	}

	debugf(NHRP_DEBUG_KERNEL, "%s: IPv%d address changed to %s",
		ifp->name, afi == AFI_IP ? 4 : 6,
		best ? prefix2str(best->address, buf, sizeof buf) : "(none)");
	if_ad->addr = addr;

	if (if_ad->configured && sockunion_family(&if_ad->addr) != AF_UNSPEC) {
		nc = nhrp_cache_get(ifp, &addr, 1);
		if (nc) nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL);
	}

	notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED);
}
Esempio n. 3
0
int
bgp_nlri_parse_encap(
    struct peer		*peer,
    struct attr		*attr, 		/* Need even for withdraw */
    struct bgp_nlri	*packet)
{
  u_char *pnt;
  u_char *lim;
  afi_t afi = packet->afi;
  struct prefix p;
  int psize = 0;
  int prefixlen;
  struct rd_as rd_as;
  struct rd_ip rd_ip;
  struct prefix_rd prd;
  struct ecommunity *pEcom = NULL;
  u_int16_t rdtype = 0xffff;
  char buf[BUFSIZ];

  /* Check peer status. */
  if (peer->status != Established)
    return 0;
  
  /* Make prefix_rd */
  if (attr && attr->extra && attr->extra->ecommunity)
      pEcom = attr->extra->ecommunity;

  ecom2prd(pEcom, &prd);
  memset(&rd_as, 0, sizeof(rd_as));
  memset(&rd_ip, 0, sizeof(rd_ip));

  if (pEcom) {

      rdtype = (prd.val[0] << 8) | prd.val[1];

      /* Decode RD value. */
      if (rdtype == RD_TYPE_AS)
	decode_rd_as (prd.val + 2, &rd_as);
      else if (rdtype == RD_TYPE_IP)
	decode_rd_ip (prd.val + 2, &rd_ip);
      else if (rdtype == RD_TYPE_AS4)
	decode_rd_as4 (prd.val + 2, &rd_as);
      else
	{
	  zlog_err ("Invalid RD type %d", rdtype);
	}

  }

  /*
   * NB: this code was based on the MPLS VPN code, which supported RDs.
   * For the moment we are retaining the underlying RIB structure that
   * keeps a per-RD radix tree, but since the RDs are not carried over
   * the wire, we set the RD internally to 0.
   */
  prd.family = AF_UNSPEC;
  prd.prefixlen = 64;
  memset(prd.val, 0, sizeof(prd.val));

  pnt = packet->nlri;
  lim = pnt + packet->length;

  for (; pnt < lim; pnt += psize)
    {
      /* Clear prefix structure. */
      memset (&p, 0, sizeof (struct prefix));

      /* Fetch prefix length. */
      prefixlen = *pnt++;
      p.family = afi2family(afi);
      if (p.family == 0) {
	/* bad afi, shouldn't happen */
	zlog_warn("%s: bad afi %d, dropping incoming route", __func__, afi);
	continue;
      }
      psize = PSIZE (prefixlen);

      p.prefixlen = prefixlen;
      memcpy (&p.u.prefix, pnt, psize);

      if (pnt + psize > lim)
	return -1;


      if (rdtype == RD_TYPE_AS)
	zlog_info ("rd-as %u:%u prefix %s/%d", rd_as.as, rd_as.val,
		   inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
		   p.prefixlen);
      else if (rdtype == RD_TYPE_IP)
	zlog_info ("rd-ip %s:%u prefix %s/%d", inet_ntoa (rd_ip.ip),
		   rd_ip.val,
		   inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
		   p.prefixlen);
      else if (rdtype == RD_TYPE_AS4)
	zlog_info ("rd-as4 %u:%u prefix %s/%d", rd_as.as, rd_as.val,
		   inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
		   p.prefixlen);
      else
	zlog_info ("rd unknown, default to 0:0 prefix %s/%d",
	    inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
	    p.prefixlen);

      if (attr) {
	bgp_update (peer, &p, attr, afi, SAFI_ENCAP,
		    ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0);
      } else {
	bgp_withdraw (peer, &p, attr, afi, SAFI_ENCAP,
		      ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL);
      }
    }

  /* Packet length consistency check. */
  if (pnt != lim)
    return -1;

  return 0;
}