diff options
| -rw-r--r-- | pimd/pim_cmd.c | 17 | ||||
| -rw-r--r-- | pimd/pim_msdp.c | 236 | ||||
| -rw-r--r-- | pimd/pim_msdp.h | 4 | ||||
| -rw-r--r-- | pimd/pim_msdp_packet.c | 25 | ||||
| -rw-r--r-- | pimd/pim_register.c | 1 | ||||
| -rw-r--r-- | pimd/pim_rp.c | 15 | ||||
| -rw-r--r-- | pimd/pim_upstream.c | 25 | ||||
| -rw-r--r-- | pimd/pim_upstream.h | 5 | 
8 files changed, 302 insertions, 26 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 5b5bf8235d..03856bdfcf 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1603,6 +1603,10 @@ json_object_pim_upstream_add (json_object *json, struct pim_upstream *up)    if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)      json_object_boolean_true_add(json, "sourceStream"); + +  /* XXX: need to print ths flag in the plain text display as well */ +  if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) +    json_object_boolean_true_add(json, "sourceMsdp");  }  static void pim_show_upstream(struct vty *vty, u_char uj) @@ -5294,13 +5298,14 @@ ip_msdp_show_sa(struct vty *vty, u_char uj)    char grp_str[INET_ADDRSTRLEN];    char rp_str[INET_ADDRSTRLEN];    char timebuf[PIM_MSDP_UPTIME_STRLEN]; +  char spt_str[2];    int64_t now;    if (uj) {      // XXX: blah      return;    } else { -    vty_out(vty, "Source                     Group               RP    Uptime%s", VTY_NEWLINE); +    vty_out(vty, "Source                     Group               RP  SPT    Uptime%s", VTY_NEWLINE);      for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) {        now = pim_time_monotonic_sec();        pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); @@ -5308,11 +5313,17 @@ ip_msdp_show_sa(struct vty *vty, u_char uj)        pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str));        if (sa->flags & PIM_MSDP_SAF_LOCAL) {          strcpy(rp_str, "local"); +        strcpy(spt_str, "-");        } else {          pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); +        if (sa->up) { +          strcpy(spt_str, "y"); +        } else { +          strcpy(spt_str, "n"); +        }        } -      vty_out(vty, "%-15s  %15s  %15s  %8s%s", -          src_str, grp_str, rp_str, timebuf, VTY_NEWLINE); +      vty_out(vty, "%-15s  %15s  %15s  %3s  %8s%s", +          src_str, grp_str, rp_str, spt_str, timebuf, VTY_NEWLINE);      }    }  } diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index d8237469c8..8e933222c6 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -82,6 +82,7 @@ pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, const char *timer_str)  static int  pim_msdp_sa_adv_timer_cb(struct thread *t)  { +  msdp->sa_adv_timer = NULL;    if (PIM_DEBUG_MSDP_INTERNAL) {      zlog_debug("MSDP SA advertisment timer expired");    } @@ -107,6 +108,7 @@ pim_msdp_sa_state_timer_cb(struct thread *t)    struct pim_msdp_sa *sa;    sa = THREAD_ARG(t); +  sa->sa_state_timer = NULL;    if (PIM_DEBUG_MSDP_EVENTS) {      pim_msdp_sa_timer_expiry_log(sa, "state"); @@ -125,6 +127,134 @@ pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start)    }  } +static void +pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) +{ +  struct pim_upstream *up = sa->up; +  if (!up) { +    return; +  } + +  sa->up = NULL; +  /* XXX: we can't pull the plug on an active flow even if the SA entry is +   * removed. so ideally we want to start the kat in parallel and let the +   * entry age out; but running the kat has fatal consequences. need to +   * check with Donald on the best way to go abt this */ +  if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { +    PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); +    pim_upstream_del(up, __PRETTY_FUNCTION__); +  } + +  if (PIM_DEBUG_MSDP_EVENTS) { +    char key_str[PIM_MSDP_SA_KEY_STRLEN]; +    pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); +    zlog_debug("%s de-referenced SPT", key_str); +  } +} + +static bool +pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up) +{ +  if (sa->flags & PIM_MSDP_SAF_LOCAL) { +    /* if there is a local reference we should NEVER use it for setting up +     * SPTs otherwise we will get stuck in a simple circular deadlock */ +    return false; +  } + +  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->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(&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; +} + +/* Upstream add evaluation needs to happen everytime - + * 1. Peer reference is added or removed. + * 2. Local reference is added or removed. + * 3. The RP for a group changes. + * 4. joinDesired for the associated (*, G) changes + * 5. 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; +  char key_str[PIM_MSDP_SA_KEY_STRLEN]; + +  if (PIM_DEBUG_MSDP_EVENTS || PIM_DEBUG_MSDP_INTERNAL) { +    pim_msdp_sa_key_dump(sa, key_str, sizeof(key_str), true); +  } + +  if (PIM_DEBUG_MSDP_INTERNAL) { +      zlog_debug("%s upstream update on %s", key_str, ctx); +  } + +  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->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("%s SPT reference missing", key_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->sg, NULL /* iif */, +                        PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, +                        __PRETTY_FUNCTION__); + +  sa->up = up; +  if (up) { +    /* update inherited oil */ +    pim_upstream_inherited_olist(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("%s referenced SPT", key_str); +    } +  } else { +    if (PIM_DEBUG_MSDP_EVENTS) { +      zlog_debug("%s SPT reference failed", key_str); +    } +  } +} +  /* release all mem associated with a sa */  static void  pim_msdp_sa_free(struct pim_msdp_sa *sa) @@ -137,8 +267,6 @@ pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp)  {    struct pim_msdp_sa *sa; -  pim_msdp_enable(); -    sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa));    if (!sa) {      zlog_err("%s: PIM XCALLOC(%zu) failure", @@ -194,6 +322,10 @@ pim_msdp_sa_add(struct prefix_sg *sg, struct in_addr rp)  static void  pim_msdp_sa_del(struct pim_msdp_sa * sa)  { +  /* this is somewhat redundant - still want to be careful not to leave +   * stale upstream references */ +  pim_msdp_sa_upstream_del(sa); +    /* stop timers */    pim_msdp_sa_state_timer_setup(sa, false /* start */); @@ -243,6 +375,7 @@ pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags)    }    sa->flags &= ~flags; +  pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref");    if (!(sa->flags & PIM_MSDP_SAF_REF)) {      pim_msdp_sa_del(sa);    } @@ -275,6 +408,10 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,      sa->peer = mp->peer;      /* start/re-start the state timer to prevent cache expiry */      pim_msdp_sa_state_timer_setup(sa, true /* start */); +    /* We re-evaluate SA "SPT-trigger" everytime we hear abt it from a +     * peer. XXX: If this becomes too much of a periodic overhead we +     * can make it event based */ +    pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref");    } else {      if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) {        sa->flags |= PIM_MSDP_SAF_LOCAL; @@ -282,8 +419,9 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg,        if (PIM_DEBUG_MSDP_EVENTS) {          zlog_debug("%s added locally", key_str);        } -      /* send an immeidate SA update to peers */ +      /* send an immediate SA update to peers */        pim_msdp_pkt_sa_tx_one(sa); +      pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "local-ref");      }      sa->flags &= ~PIM_MSDP_SAF_STALE;    } @@ -338,28 +476,100 @@ pim_msdp_sa_local_setup(void)    }  } -/* whenever the RP changes we need to re-evaluate the "local" - * SA-cache */ -/* XXX: need to call this from thr right places. also needs more testing */ +/* whenever the RP changes we need to re-evaluate the "local" SA-cache */ +/* XXX: needs to be tested */  void  pim_msdp_i_am_rp_changed(void)  {    struct listnode *sanode;    struct pim_msdp_sa *sa; +  if (!(msdp->flags & PIM_MSDPF_ENABLE)) { +    /* if the feature is not enabled do nothing */ +    return; +  } + +  if (PIM_DEBUG_MSDP_INTERNAL) { +      zlog_debug("MSDP i_am_rp changed");  +  } +    /* mark all local entries as stale */    for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { -    sa->flags |= PIM_MSDP_SAF_STALE; +    if (sa->flags & PIM_MSDP_SAF_LOCAL) { +      sa->flags |= PIM_MSDP_SAF_STALE; +    }    }    /* re-setup local SA entries */    pim_msdp_sa_local_setup(); -  /* purge stale SA entries */    for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +    /* purge stale SA entries */      if (sa->flags & PIM_MSDP_SAF_STALE) { +      /* clear the stale flag; the entry may be kept even after +       * "local-deref" */ +      sa->flags &= ~PIM_MSDP_SAF_STALE;        pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL);      } +    /* also check if we can still influence SPT */ +    pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "rp-change"); +  } +} + +/* We track the join state of (*, G) entries. If G has sources in the SA-cache + * we need to setup or teardown SPT when the JoinDesired status changes for + * (*, G) */ +void +pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) +{ +  struct listnode *sanode; +  struct pim_msdp_sa *sa; + +  if (PIM_DEBUG_MSDP_INTERNAL) { +      zlog_debug("MSDP join state changed for %s", pim_str_sg_dump(&xg_up->sg));  +  } + +  /* If this is not really an XG entry just move on */ +  if ((xg_up->sg.src.s_addr != INADDR_ANY) || +      (xg_up->sg.grp.s_addr == INADDR_ANY)) { +    return; +  } + +  /* XXX: Need to maintain SAs per-group to avoid all this unnecessary +   * walking */ +  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +    if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { +      continue; +    } +    pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); +  } +} + +/* XXX: Need to maintain SAs per-group to avoid all this unnecessary + * walking */ +void +pim_msdp_up_xg_del(struct prefix_sg *sg) +{ +  struct listnode *sanode; +  struct pim_msdp_sa *sa; + +  if (PIM_DEBUG_MSDP_INTERNAL) { +      zlog_debug("MSDP %s del", pim_str_sg_dump(sg));  +  } + +  /* If this is not really an XG entry just move on */ +  if ((sg->src.s_addr != INADDR_ANY) || +      (sg->grp.s_addr == INADDR_ANY)) { +    return; +  } + +  /* XXX: Need to maintain SAs per-group to avoid all this unnecessary +   * walking */ +  for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { +    if (sa->sg.grp.s_addr != sg->grp.s_addr) { +      continue; +    } +    pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change");    }  } @@ -536,6 +746,12 @@ pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state)      }    } +  if (PIM_DEBUG_MSDP_INTERNAL) { +    char key_str[PIM_MSDP_PEER_KEY_STRLEN]; + +    pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); +    zlog_debug("%s pim_msdp_peer_stop_tcp_conn", key_str); +  }    /* stop read and write threads */    PIM_MSDP_PEER_READ_OFF(mp);    PIM_MSDP_PEER_WRITE_OFF(mp); @@ -594,6 +810,7 @@ pim_msdp_peer_hold_timer_cb(struct thread *t)    struct pim_msdp_peer *mp;    mp = THREAD_ARG(t); +  mp->hold_timer = NULL;    if (PIM_DEBUG_MSDP_EVENTS) {      pim_msdp_peer_timer_expiry_log(mp, "hold"); @@ -627,6 +844,7 @@ pim_msdp_peer_ka_timer_cb(struct thread *t)    struct pim_msdp_peer *mp;    mp = THREAD_ARG(t); +  mp->ka_timer = NULL;    if (PIM_DEBUG_MSDP_EVENTS) {      pim_msdp_peer_timer_expiry_log(mp, "ka"); @@ -636,7 +854,6 @@ pim_msdp_peer_ka_timer_cb(struct thread *t)    pim_msdp_peer_ka_timer_setup(mp, true /* start */);    return 0;  } -/* XXX: reset this anytime a message is sent to the peer */  static void  pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start)  { @@ -690,6 +907,7 @@ pim_msdp_peer_cr_timer_cb(struct thread *t)    struct pim_msdp_peer *mp;    mp = THREAD_ARG(t); +  mp->cr_timer = NULL;    if (PIM_DEBUG_MSDP_EVENTS) {      pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 2af453f689..5e13b33b5b 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -81,6 +81,8 @@ struct pim_msdp_sa {  #define PIM_MSDP_SA_HOLD_TIME ((3*60)+30)    struct thread *sa_state_timer;  // 5.6    int64_t uptime; + +  struct pim_upstream *up;  };  enum pim_msdp_peer_flags { @@ -193,4 +195,6 @@ void pim_msdp_sa_local_add(struct prefix_sg *sg);  void pim_msdp_sa_local_del(struct prefix_sg *sg);  void pim_msdp_i_am_rp_changed(void);  bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp); +void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up); +void pim_msdp_up_xg_del(struct prefix_sg *sg);  #endif diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index d6b4765714..bc6156325f 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -150,14 +150,17 @@ pim_msdp_write(struct thread *thread)    struct stream *s;    int num;    enum pim_msdp_tlv type; +  int work_cnt = 0; +  char key_str[PIM_MSDP_PEER_KEY_STRLEN];    mp = THREAD_ARG(thread);    mp->t_write = NULL;    if (PIM_DEBUG_MSDP_INTERNAL) { -    char key_str[PIM_MSDP_PEER_KEY_STRLEN]; -      pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false); +  } + +  if (PIM_DEBUG_MSDP_INTERNAL) {      zlog_debug("%s pim_msdp_write", key_str);    }    if (mp->fd < 0) { @@ -176,7 +179,7 @@ pim_msdp_write(struct thread *thread)      return 0;    } -  sockopt_cork (mp->fd, 1); +  sockopt_cork(mp->fd, 1);    /* Nonblocking write until TCP output buffer is full  */    do @@ -190,8 +193,12 @@ pim_msdp_write(struct thread *thread)      num = write(mp->fd, STREAM_PNT(s), writenum);      if (num < 0) {        /* write failed either retry needed or error */ -      if (ERRNO_IO_RETRY(errno)) +      if (ERRNO_IO_RETRY(errno)) { +        if (PIM_DEBUG_MSDP_INTERNAL) { +          zlog_debug("%s pim_msdp_write io retry", key_str); +        }          break; +      }        /* XXX:revisit; reset TCP connection */        pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); @@ -202,9 +209,6 @@ pim_msdp_write(struct thread *thread)        /* Partial write */        stream_forward_getp(s, num);        if (PIM_DEBUG_MSDP_INTERNAL) { -        char key_str[PIM_MSDP_PEER_KEY_STRLEN]; - -        pim_msdp_peer_key_dump(mp, key_str, sizeof(key_str), false);          zlog_debug("%s pim_msdp_partial_write", key_str);        }        break; @@ -230,12 +234,17 @@ pim_msdp_write(struct thread *thread)      /* packet sent delete it. */      pim_msdp_pkt_delete(mp); +    ++work_cnt;      /* XXX - may need to pause if we have done too much work in this       * loop */    } while ((s = stream_fifo_head(mp->obuf)) != NULL);    pim_msdp_write_proceed_actions(mp); -  sockopt_cork (mp->fd, 0); +  sockopt_cork(mp->fd, 0); + +  if (PIM_DEBUG_MSDP_INTERNAL) { +    zlog_debug("%s pim_msdp_write wrote %d packets", key_str, work_cnt); +  }    return 0;  } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index e012115e37..3058df1af4 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -352,6 +352,7 @@ pim_register_recv (struct interface *ifp,                {                  zlog_debug ("Received Register(%s), for which I have no path back", pim_str_sg_dump (&upstream->sg));                } +            pim_upstream_unset_created_by_upstream(upstream);              pim_upstream_del (upstream, __PRETTY_FUNCTION__);              return 1;            } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 817837afbf..1bd48798c6 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -40,6 +40,7 @@  #include "pim_sock.h"  #include "pim_memory.h"  #include "pim_iface.h" +#include "pim_msdp.h"  struct rp_info  { @@ -226,6 +227,7 @@ pim_rp_find_match_group (struct prefix *group)  static void  pim_rp_refresh_group_to_rp_mapping()  { +  pim_msdp_i_am_rp_changed();  }  void @@ -509,6 +511,7 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new)  {    struct listnode *node;    struct rp_info *rp_info; +  bool i_am_rp_changed = false;    if (qpim_rp_list == NULL)      return; @@ -529,14 +532,24 @@ pim_rp_check_rp (struct in_addr old, struct in_addr new)        if (new.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr)          { -	  rp_info->i_am_rp = 1; +          if (!rp_info->i_am_rp) { +            i_am_rp_changed = true; +          } +          rp_info->i_am_rp = 1;          }        if (old.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr)          { +          if (rp_info->i_am_rp) { +            i_am_rp_changed = true; +          }            rp_info->i_am_rp = 0;          }      } + +    if (i_am_rp_changed) { +      pim_msdp_i_am_rp_changed(); +    }  }  /* diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 2596f8c6e1..2abf0b296f 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -119,7 +119,7 @@ pim_upstream_set_created_by_upstream(struct pim_upstream *up)    pim_msdp_sa_local_add(&up->sg);  } -static void +void  pim_upstream_unset_created_by_upstream(struct pim_upstream *up)  {    PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(up->flags); @@ -169,6 +169,8 @@ static void upstream_channel_oil_detach(struct pim_upstream *up)  void  pim_upstream_del(struct pim_upstream *up, const char *name)  { +  bool notify_msdp = false; +    if (PIM_DEBUG_PIM_TRACE)      {        zlog_debug ("%s: Delete (%s) ref count: %d", @@ -187,10 +189,20 @@ pim_upstream_del(struct pim_upstream *up, const char *name)    THREAD_OFF(up->t_ka_timer);    THREAD_OFF(up->t_rs_timer); +  if (up->join_state == PIM_UPSTREAM_JOINED) { +    pim_joinprune_send (up->rpf.source_nexthop.interface, +                      up->rpf.rpf_addr.u.prefix4, +                      up, 0); +    if (up->sg.src.s_addr == INADDR_ANY) { +        /* if a (*, G) entry in the joined state is being deleted we +         * need to notify MSDP */ +        notify_msdp = true; +    } +  } +    if (up->sg.src.s_addr != INADDR_ANY)      wheel_remove_item (pim_upstream_sg_wheel, up); -  pim_msdp_sa_local_del(&up->sg);    pim_upstream_remove_children (up);    pim_mroute_del (up->channel_oil);    upstream_channel_oil_detach(up); @@ -212,6 +224,9 @@ pim_upstream_del(struct pim_upstream *up, const char *name)    listnode_delete (pim_upstream_list, up);    hash_release (pim_upstream_hash, up); +  if (notify_msdp) { +    pim_msdp_up_xg_del(&up->sg); +  }    pim_upstream_free(up);  } @@ -465,6 +480,7 @@ pim_upstream_switch(struct pim_upstream *up,        {          int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags);          forward_on(up); +        pim_msdp_up_join_state_changed(up);  	if (pim_upstream_could_register (up))  	  {              PIM_UPSTREAM_FLAG_SET_FHR(up->flags); @@ -487,6 +503,8 @@ pim_upstream_switch(struct pim_upstream *up,    }    else {      forward_off(up); +    if (old_state == PIM_UPSTREAM_JOINED) +      pim_msdp_up_join_state_changed(up);      pim_joinprune_send(up->rpf.source_nexthop.interface,  		       up->rpf.rpf_addr.u.prefix4,  		       up, @@ -925,9 +943,6 @@ pim_upstream_keep_alive_timer (struct thread *t)        pim_mroute_del (up->channel_oil);        THREAD_OFF (up->t_ka_timer);        THREAD_OFF (up->t_rs_timer); -      THREAD_OFF (up->t_join_timer); -      pim_joinprune_send (up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4, -                          up, 0);        PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM (up->flags);        if (PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(up->flags))  	{ diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 7f8c0c99cb..a073125021 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -34,6 +34,7 @@  #define PIM_UPSTREAM_FLAG_MASK_SRC_PIM                 (1 << 4)  #define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM              (1 << 5)  #define PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM     (1 << 6) +#define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP                (1 << 7)  #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)  #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) @@ -42,6 +43,7 @@  #define PIM_UPSTREAM_FLAG_TEST_SRC_PIM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)  #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)  #define PIM_UPSTREAM_FLAG_TEST_CREATED_BY_UPSTREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM) +#define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)  #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)  #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) @@ -50,6 +52,7 @@  #define PIM_UPSTREAM_FLAG_SET_SRC_PIM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_PIM)  #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)  #define PIM_UPSTREAM_FLAG_SET_CREATED_BY_UPSTREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM) +#define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)  #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)  #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) @@ -58,6 +61,7 @@  #define PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_PIM)  #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)  #define PIM_UPSTREAM_FLAG_UNSET_CREATED_BY_UPSTREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_CREATED_BY_UPSTREAM) +#define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)  enum pim_upstream_state {    PIM_UPSTREAM_NOTJOINED, @@ -164,4 +168,5 @@ void pim_upstream_find_new_rpf (void);  void pim_upstream_init (void);  void pim_upstream_terminate (void);  void pim_upstream_set_created_by_upstream(struct pim_upstream *up); +void pim_upstream_unset_created_by_upstream(struct pim_upstream *up);  #endif /* PIM_UPSTREAM_H */  | 
