Пример #1
0
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->pim, sa->sg.grp)) {
		return false;
	}

	/* 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;

		xg_up = pim_upstream_find(sa->pim, &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;
}
Пример #2
0
/* Upstream add evaluation needs to happen everytime -
 * 1. Peer reference is added or removed.
 * 2. The RP for a group changes.
 * 3. joinDesired for the associated (*, G) changes
 * 4. associated (*, G) is removed - this seems like a bit redundant
 *    (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->pim, &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->pim, &sa->sg, NULL /* iif */,
			      PIM_UPSTREAM_FLAG_MASK_SRC_MSDP,
			      __PRETTY_FUNCTION__, NULL);

	sa->up = up;
	if (up) {
		/* update inherited oil */
		pim_upstream_inherited_olist(sa->pim, 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);
		}
	}
}
struct pim_upstream *pim_upstream_add(struct in_addr source_addr,
				      struct in_addr group_addr)
{
  struct pim_upstream *up;

  up = pim_upstream_find(source_addr, group_addr);
  if (up) {
    ++up->ref_count;
  }
  else {
    up = pim_upstream_new(source_addr, group_addr);
  }

  return up;
}
Пример #4
0
/* For every VxLAN BUM multicast group we setup a SG-up that has the following
 * "forced properties" -
 * 1. Directly connected on a DR interface i.e. we must act as an FHR
 * 2. We prime the pump i.e. no multicast data is needed to register this
 *    source with the FHR. To do that we send periodic null registers if
 *    the SG entry is in a register-join state. We also prevent expiry of
 *    KAT.
 * 3. As this SG is setup without data there is no need to register encapsulate
 *    data traffic. This encapsulation is explicitly skipped for the following
 *    reasons -
 *    a) Many levels of encapsulation are needed creating MTU disc challenges.
 *       Overlay BUM is encapsulated in a vxlan/UDP/IP header and then
 *       encapsulated again in a pim-register header.
 *    b) On a vxlan-aa setup both switches rx a copy of each BUM packet. if
 *       they both reg encapsulated traffic the RP will accept the duplicates
 *       as there are no RPF checks for this encapsulated data.
 *    a), b) can be workarounded if needed, but there is really no need because
 *    of (2) i.e. the pump is primed without data.
 */
static void pim_vxlan_orig_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
{
	struct pim_upstream *up;
	int flags = 0;
	struct prefix nht_p;

	if (vxlan_sg->up) {
		/* nothing to do */
		return;
	}

	if (PIM_DEBUG_VXLAN)
		zlog_debug("vxlan SG %s orig mroute-up add with iif %s",
			vxlan_sg->sg_str,
			vxlan_sg->iif?vxlan_sg->iif->name:"-");

	PIM_UPSTREAM_FLAG_SET_SRC_VXLAN_ORIG(flags);
	/* pin the IIF to lo or peerlink-subinterface and disable NHT */
	PIM_UPSTREAM_FLAG_SET_STATIC_IIF(flags);
	/* Fake traffic by setting SRC_STREAM and starting KAT */
	/* We intentionally skip updating ref count for SRC_STREAM/FHR.
	 * Setting SRC_VXLAN should have already created a reference
	 * preventing the entry from being deleted
	 */
	PIM_UPSTREAM_FLAG_SET_FHR(flags);
	PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags);
	/* Force pimreg even if non-DR. This is needed on a MLAG setup for
	 * VxLAN AA
	 */
	PIM_UPSTREAM_FLAG_SET_FORCE_PIMREG(flags);
	/* prevent KAT expiry. we want the MDT setup even if there is no BUM
	 * traffic
	 */
	PIM_UPSTREAM_FLAG_SET_DISABLE_KAT_EXPIRY(flags);
	/* SPT for vxlan BUM groups is primed and maintained via NULL
	 * registers so there is no need to reg-encapsulate
	 * vxlan-encapsulated overlay data traffic
	 */
	PIM_UPSTREAM_FLAG_SET_NO_PIMREG_DATA(flags);
	/* On a MLAG setup we force a copy to the MLAG peer while also
	 * accepting traffic from the peer. To do this we set peerlink-rif as
	 * the IIF and also add it to the OIL
	 */
	PIM_UPSTREAM_FLAG_SET_ALLOW_IIF_IN_OIL(flags);

	/* XXX: todo: defer pim_upstream add if pim is not enabled on the iif */
	up = pim_upstream_find(vxlan_sg->pim, &vxlan_sg->sg);
	if (up) {
		/* if the iif is set to something other than the vxlan_sg->iif
		 * we must dereg the old nexthop and force to new "static"
		 * iif
		 */
		if (!PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)) {
			nht_p.family = AF_INET;
			nht_p.prefixlen = IPV4_MAX_BITLEN;
			nht_p.u.prefix4 = up->upstream_addr;
			pim_delete_tracked_nexthop(vxlan_sg->pim,
				&nht_p, up, NULL, false);
		}
		pim_upstream_ref(up, flags, __PRETTY_FUNCTION__);
		vxlan_sg->up = up;
		pim_vxlan_orig_mr_up_iif_update(vxlan_sg);
	} else {
		up = pim_upstream_add(vxlan_sg->pim, &vxlan_sg->sg,
				vxlan_sg->iif, flags,
				__PRETTY_FUNCTION__, NULL);
		vxlan_sg->up = up;
	}

	if (!up) {
		if (PIM_DEBUG_VXLAN)
			zlog_debug("vxlan SG %s orig mroute-up add failed",
					vxlan_sg->sg_str);
		return;
	}

	pim_upstream_keep_alive_timer_start(up, vxlan_sg->pim->keep_alive_time);

	/* register the source with the RP */
	if (up->reg_state == PIM_REG_NOINFO) {
		pim_register_join(up);
		pim_null_register_send(up);
	}

	/* update the inherited OIL */
	pim_upstream_inherited_olist(vxlan_sg->pim, up);
}