static struct pim_upstream *pim_upstream_new(struct in_addr source_addr,
					     struct in_addr group_addr)
{
  struct pim_upstream *up;

  up = XMALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up));
  if (!up) {
    zlog_err("%s: PIM XMALLOC(%zu) failure",
	     __PRETTY_FUNCTION__, sizeof(*up));
    return 0;
  }
  
  up->source_addr                = source_addr;
  up->group_addr                 = group_addr;
  up->flags                      = 0;
  up->ref_count                  = 1;
  up->t_join_timer               = 0;
  up->join_state                 = 0;
  up->state_transition           = pim_time_monotonic_sec();
  up->channel_oil                = 0;

  up->rpf.source_nexthop.interface                = 0;
  up->rpf.source_nexthop.mrib_nexthop_addr.s_addr = PIM_NET_INADDR_ANY;
  up->rpf.source_nexthop.mrib_metric_preference   = qpim_infinite_assert_metric.metric_preference;
  up->rpf.source_nexthop.mrib_route_metric        = qpim_infinite_assert_metric.route_metric;
  up->rpf.rpf_addr.s_addr                         = PIM_NET_INADDR_ANY;

  pim_rpf_update(up, 0);

  listnode_add(qpim_upstream_list, up);

  return up;
}
Ejemplo n.º 2
0
static void scan_upstream_rpf_cache()
{
  struct listnode     *up_node;
  struct listnode     *up_nextnode;
  struct pim_upstream *up;

  for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) {
    struct in_addr      old_rpf_addr;
    enum pim_rpf_result rpf_result;

    rpf_result = pim_rpf_update(up, &old_rpf_addr);
    if (rpf_result == PIM_RPF_FAILURE)
      continue;

    if (rpf_result == PIM_RPF_CHANGED) {
      
      if (up->join_state == PIM_UPSTREAM_JOINED) {
	
	/*
	  RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Messages
	  
	  Transitions from Joined State
	  
	  RPF'(S,G) changes not due to an Assert
	  
	  The upstream (S,G) state machine remains in Joined
	  state. Send Join(S,G) to the new upstream neighbor, which is
	  the new value of RPF'(S,G).  Send Prune(S,G) to the old
	  upstream neighbor, which is the old value of RPF'(S,G).  Set
	  the Join Timer (JT) to expire after t_periodic seconds.
	*/

    
	/* send Prune(S,G) to the old upstream neighbor */
	pim_joinprune_send(up->rpf.source_nexthop.interface,
			   old_rpf_addr,
			   up->source_addr,
			   up->group_addr,
			   0 /* prune */);
	
	/* send Join(S,G) to the current upstream neighbor */
	pim_joinprune_send(up->rpf.source_nexthop.interface,
			   up->rpf.rpf_addr,
			   up->source_addr,
			   up->group_addr,
			   1 /* join */);

	pim_upstream_join_timer_restart(up);
      } /* up->join_state == PIM_UPSTREAM_JOINED */

      /* FIXME can join_desired actually be changed by pim_rpf_update()
	 returning PIM_RPF_CHANGED ? */
      pim_upstream_update_join_desired(up);

    } /* PIM_RPF_CHANGED */

  } /* for (qpim_upstream_list) */
  
}
Ejemplo n.º 3
0
/**************************** vxlan origination mroutes ***********************
 * For every (local-vtep-ip, bum-mcast-grp) registered by evpn an origination
 * mroute is setup by pimd. The purpose of this mroute is to forward vxlan
 * encapsulated BUM (broadcast, unknown-unicast and unknown-multicast packets
 * over the underlay.)
 *
 * Sample mroute (single VTEP):
 * (27.0.0.7, 239.1.1.100)     Iif: lo      Oifs: uplink-1
 *
 * Sample mroute (anycast VTEP):
 * (36.0.0.9, 239.1.1.100)          Iif: peerlink-3.4094\
 *                                       Oifs: peerlink-3.4094 uplink-1
 ***************************************************************************/
static void pim_vxlan_orig_mr_up_del(struct pim_vxlan_sg *vxlan_sg)
{
	struct pim_upstream *up = vxlan_sg->up;

	if (!up)
		return;

	if (PIM_DEBUG_VXLAN)
		zlog_debug("vxlan SG %s orig mroute-up del",
			vxlan_sg->sg_str);

	vxlan_sg->up = NULL;
	if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG) {
		/* clear out all the vxlan properties */
		up->flags &= ~(PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG |
			PIM_UPSTREAM_FLAG_MASK_STATIC_IIF |
			PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY |
			PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG |
			PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA |
			PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL);

		/* We bring things to a grinding halt by force expirying
		 * the kat. Doing this will also remove the reference we
		 * created as a "vxlan" source and delete the upstream entry
		 * if there are no other references.
		 */
		if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
			THREAD_OFF(up->t_ka_timer);
			up = pim_upstream_keep_alive_timer_proc(up);
		} else {
			/* this is really unexpected as we force vxlan
			 * origination mroutes active sources but just in
			 * case
			 */
			up = pim_upstream_del(vxlan_sg->pim, up,
				__PRETTY_FUNCTION__);
		}
		/* if there are other references register the source
		 * for nht
		 */
		if (up)
			pim_rpf_update(vxlan_sg->pim, up, NULL, 1 /* is_new */);
	}
}