Diff for /embedaddon/bird/proto/bgp/bgp.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2017/08/22 12:33:54 version 1.1.1.2, 2021/03/17 19:50:23
Line 290  bgp_update_startup_delay(struct bgp_proto *p) Line 290  bgp_update_startup_delay(struct bgp_proto *p)
 }  }
   
 static void  static void
bgp_graceful_close_conn(struct bgp_conn *conn, unsigned subcode)bgp_graceful_close_conn(struct bgp_conn *conn, uint subcode, byte *data, uint len)
 {  {
   switch (conn->state)    switch (conn->state)
     {      {
Line 304  bgp_graceful_close_conn(struct bgp_conn *conn, unsigne Line 304  bgp_graceful_close_conn(struct bgp_conn *conn, unsigne
     case BS_OPENSENT:      case BS_OPENSENT:
     case BS_OPENCONFIRM:      case BS_OPENCONFIRM:
     case BS_ESTABLISHED:      case BS_ESTABLISHED:
      bgp_error(conn, 6, subcode, NULL, 0);      bgp_error(conn, 6, subcode, data, len);
       return;        return;
     default:      default:
       bug("bgp_graceful_close_conn: Unknown state %d", conn->state);        bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
Line 340  bgp_decision(void *vp) Line 340  bgp_decision(void *vp)
 }  }
   
 void  void
bgp_stop(struct bgp_proto *p, unsigned subcode)bgp_stop(struct bgp_proto *p, uint subcode, byte *data, uint len)
 {  {
   proto_notify_state(&p->p, PS_STOP);    proto_notify_state(&p->p, PS_STOP);
  bgp_graceful_close_conn(&p->outgoing_conn, subcode);  bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
  bgp_graceful_close_conn(&p->incoming_conn, subcode);  bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len);
   ev_schedule(p->event);    ev_schedule(p->event);
 }  }
   
Line 352  static inline void Line 352  static inline void
 bgp_conn_set_state(struct bgp_conn *conn, unsigned new_state)  bgp_conn_set_state(struct bgp_conn *conn, unsigned new_state)
 {  {
   if (conn->bgp->p.mrtdump & MD_STATES)    if (conn->bgp->p.mrtdump & MD_STATES)
    mrt_dump_bgp_state_change(conn, conn->state, new_state);    bgp_dump_state_change(conn, conn->state, new_state);
   
   conn->state = new_state;    conn->state = new_state;
 }  }
Line 394  bgp_conn_enter_established_state(struct bgp_conn *conn Line 394  bgp_conn_enter_established_state(struct bgp_conn *conn
   if (p->p.gr_recovery && (p->cf->gr_mode == BGP_GR_ABLE) && peer_gr_ready)    if (p->p.gr_recovery && (p->cf->gr_mode == BGP_GR_ABLE) && peer_gr_ready)
     p->p.gr_wait = 1;      p->p.gr_wait = 1;
   
  if (p->gr_active)  if (p->gr_active == BGP_GRS_ACTIVE)
     tm_stop(p->gr_timer);      tm_stop(p->gr_timer);
   
  if (p->gr_active && (!conn->peer_gr_able || !(conn->peer_gr_aflags & BGP_GRF_FORWARDING)))  /* Check F-bit for regular graceful restart */
   if ((p->gr_active == BGP_GRS_ACTIVE) &&
       (!conn->peer_gr_able || !(conn->peer_gr_aflags & BGP_GRF_FORWARDING)))
     bgp_graceful_restart_done(p);      bgp_graceful_restart_done(p);
   
     /* Check F-bit for long-lived graceful restart */
     if (((p->gr_active == BGP_GRS_LLGR_1) || (p->gr_active == BGP_GRS_LLGR_2)) &&
         (!conn->peer_llgr_able || !(conn->peer_llgr_aflags & BGP_LLGRF_FORWARDING)))
       bgp_graceful_restart_done(p);
   
   /* GR capability implies that neighbor will send End-of-RIB */    /* GR capability implies that neighbor will send End-of-RIB */
   if (conn->peer_gr_aware)    if (conn->peer_gr_aware)
     p->load_state = BFS_LOADING;      p->load_state = BFS_LOADING;
Line 420  bgp_conn_leave_established_state(struct bgp_proto *p) Line 427  bgp_conn_leave_established_state(struct bgp_proto *p)
   bgp_free_bucket_table(p);    bgp_free_bucket_table(p);
   
   if (p->p.proto_state == PS_UP)    if (p->p.proto_state == PS_UP)
    bgp_stop(p, 0);    bgp_stop(p, 0, NULL, 0);
 }  }
   
 void  void
Line 474  bgp_handle_graceful_restart(struct bgp_proto *p) Line 481  bgp_handle_graceful_restart(struct bgp_proto *p)
             p->gr_active ? " - already pending" : "");              p->gr_active ? " - already pending" : "");
   proto_notify_state(&p->p, PS_START);    proto_notify_state(&p->p, PS_START);
   
  if (p->gr_active)  switch (p->gr_active)
   {
   case BGP_GRS_ACTIVE:
     rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);      rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);
       break;
   
  p->gr_active = 1;  case BGP_GRS_LLGR_1:
  bgp_start_timer(p->gr_timer, p->conn->peer_gr_time);    rt_refresh_begin(p->p.main_ahook->table, p->p.main_ahook);
     return;
 
   case BGP_GRS_LLGR_2:
     rt_refresh_begin(p->p.main_ahook->table, p->p.main_ahook);
     rt_modify_stale(p->p.main_ahook->table, p->p.main_ahook);
     return;
   }
 
   p->stale_time = p->cf->llgr_mode ? p->conn->peer_llgr_time : 0;
   p->gr_active = !p->stale_time ? BGP_GRS_ACTIVE : BGP_GRS_LLGR_1;
   tm_start(p->gr_timer, p->conn->peer_gr_time);
   rt_refresh_begin(p->p.main_ahook->table, p->p.main_ahook);    rt_refresh_begin(p->p.main_ahook->table, p->p.main_ahook);
 }  }
   
Line 515  bgp_graceful_restart_timeout(timer *t) Line 536  bgp_graceful_restart_timeout(timer *t)
 {  {
   struct bgp_proto *p = t->data;    struct bgp_proto *p = t->data;
   
  BGP_TRACE(D_EVENTS, "Neighbor graceful restart timeout");  switch (p->gr_active)
  bgp_stop(p, 0);  {
}  case BGP_GRS_ACTIVE:
     BGP_TRACE(D_EVENTS, "Neighbor graceful restart timeout");
     bgp_stop(p, 0, NULL, 0);
     return;
   
     case BGP_GRS_LLGR_1:
       BGP_TRACE(D_EVENTS, "Neighbor graceful restart timeout");
       p->gr_active = BGP_GRS_LLGR_2;
       tm_start(p->gr_timer, p->stale_time);
       rt_modify_stale(p->p.main_ahook->table, p->p.main_ahook);
       return;
   
     case BGP_GRS_LLGR_2:
       BGP_TRACE(D_EVENTS, "Long-lived graceful restart timeout");
       p->gr_active = 0;
       rt_refresh_end(p->p.main_ahook->table, p->p.main_ahook);
       return;
     }
   }
   
 /**  /**
  * bgp_refresh_begin - start incoming enhanced route refresh sequence   * bgp_refresh_begin - start incoming enhanced route refresh sequence
  * @p: BGP instance   * @p: BGP instance
Line 576  bgp_send_open(struct bgp_conn *conn) Line 614  bgp_send_open(struct bgp_conn *conn)
   conn->peer_gr_time = 0;    conn->peer_gr_time = 0;
   conn->peer_gr_flags = 0;    conn->peer_gr_flags = 0;
   conn->peer_gr_aflags = 0;    conn->peer_gr_aflags = 0;
     conn->peer_llgr_aware = 0;
     conn->peer_llgr_able = 0;
     conn->peer_llgr_time = 0;
     conn->peer_llgr_aflags = 0;
   conn->peer_ext_messages_support = 0;    conn->peer_ext_messages_support = 0;
   
   DBG("BGP: Sending open\n");    DBG("BGP: Sending open\n");
Line 662  bgp_hold_timeout(timer *t) Line 704  bgp_hold_timeout(timer *t)
   
   if (sk_rx_ready(conn->sk) > 0)    if (sk_rx_ready(conn->sk) > 0)
     bgp_start_timer(conn->hold_timer, 10);      bgp_start_timer(conn->hold_timer, 10);
     else if ((conn->state == BS_ESTABLISHED) && p->gr_ready && conn->peer_llgr_able)
     {
       BGP_TRACE(D_EVENTS, "Hold timer expired");
       bgp_handle_graceful_restart(p);
       bgp_conn_enter_idle_state(conn);
     }
   else    else
     bgp_error(conn, 4, 0, NULL, 0);      bgp_error(conn, 4, 0, NULL, 0);
 }  }
Line 745  bgp_connect(struct bgp_proto *p) /* Enter Connect stat Line 793  bgp_connect(struct bgp_proto *p) /* Enter Connect stat
   s->daddr = p->cf->remote_ip;    s->daddr = p->cf->remote_ip;
   s->dport = p->cf->remote_port;    s->dport = p->cf->remote_port;
   s->iface = p->neigh ? p->neigh->iface : NULL;    s->iface = p->neigh ? p->neigh->iface : NULL;
     s->vrf = p->p.vrf;
   s->ttl = p->cf->ttl_security ? 255 : hops;    s->ttl = p->cf->ttl_security ? 255 : hops;
   s->rbsize = p->cf->enable_extended_messages ? BGP_RX_BUFFER_EXT_SIZE : BGP_RX_BUFFER_SIZE;    s->rbsize = p->cf->enable_extended_messages ? BGP_RX_BUFFER_EXT_SIZE : BGP_RX_BUFFER_SIZE;
   s->tbsize = p->cf->enable_extended_messages ? BGP_TX_BUFFER_EXT_SIZE : BGP_TX_BUFFER_SIZE;    s->tbsize = p->cf->enable_extended_messages ? BGP_TX_BUFFER_EXT_SIZE : BGP_TX_BUFFER_SIZE;
Line 790  bgp_find_proto(sock *sk) Line 839  bgp_find_proto(sock *sk)
       {        {
         struct bgp_proto *p = (struct bgp_proto *) pc->proto;          struct bgp_proto *p = (struct bgp_proto *) pc->proto;
         if (ipa_equal(p->cf->remote_ip, sk->daddr) &&          if (ipa_equal(p->cf->remote_ip, sk->daddr) &&
            (!ipa_is_link_local(sk->daddr) || (p->cf->iface == sk->iface)))            (!p->cf->iface || (p->cf->iface == sk->iface)))
           return p;            return p;
       }        }
   
Line 972  bgp_neigh_notify(neighbor *n) Line 1021  bgp_neigh_notify(neighbor *n)
           BGP_TRACE(D_EVENTS, "Neighbor lost");            BGP_TRACE(D_EVENTS, "Neighbor lost");
           bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);            bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
           /* Perhaps also run bgp_update_startup_delay(p)? */            /* Perhaps also run bgp_update_startup_delay(p)? */
          bgp_stop(p, 0);          bgp_stop(p, 0, NULL, 0);
         }          }
     }      }
   else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))    else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
Line 983  bgp_neigh_notify(neighbor *n) Line 1032  bgp_neigh_notify(neighbor *n)
           bgp_store_error(p, NULL, BE_MISC, BEM_LINK_DOWN);            bgp_store_error(p, NULL, BE_MISC, BEM_LINK_DOWN);
           if (ps == PS_UP)            if (ps == PS_UP)
             bgp_update_startup_delay(p);              bgp_update_startup_delay(p);
          bgp_stop(p, 0);          bgp_stop(p, 0, NULL, 0);
         }          }
     }      }
   else    else
Line 1003  bgp_bfd_notify(struct bfd_request *req) Line 1052  bgp_bfd_notify(struct bfd_request *req)
   int ps = p->p.proto_state;    int ps = p->p.proto_state;
   
   if (req->down && ((ps == PS_START) || (ps == PS_UP)))    if (req->down && ((ps == PS_START) || (ps == PS_UP)))
     {
       BGP_TRACE(D_EVENTS, "BFD session down");
       bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);
   
       if (p->cf->bfd == BGP_BFD_GRACEFUL)
     {      {
      BGP_TRACE(D_EVENTS, "BFD session down");      /* Trigger graceful restart */
      bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);      if (p->conn && (p->conn->state == BS_ESTABLISHED) && p->gr_ready)
         bgp_handle_graceful_restart(p);
 
       if (p->incoming_conn.state > BS_IDLE)
         bgp_conn_enter_idle_state(&p->incoming_conn);
 
       if (p->outgoing_conn.state > BS_IDLE)
         bgp_conn_enter_idle_state(&p->outgoing_conn);
     }
     else
     {
       /* Trigger session down */
       if (ps == PS_UP)        if (ps == PS_UP)
         bgp_update_startup_delay(p);          bgp_update_startup_delay(p);
      bgp_stop(p, 0);      bgp_stop(p, 0, NULL, 0);
     }      }
     }
 }  }
   
 static void  static void
Line 1018  bgp_update_bfd(struct bgp_proto *p, int use_bfd) Line 1084  bgp_update_bfd(struct bgp_proto *p, int use_bfd)
   if (use_bfd && !p->bfd_req)    if (use_bfd && !p->bfd_req)
     p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr,      p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr,
                                      p->cf->multihop ? NULL : p->neigh->iface,                                       p->cf->multihop ? NULL : p->neigh->iface,
                                     bgp_bfd_notify, p);                                     p->p.vrf, bgp_bfd_notify, p);
   
   if (!use_bfd && p->bfd_req)    if (!use_bfd && p->bfd_req)
     {      {
Line 1180  bgp_start(struct proto *P) Line 1246  bgp_start(struct proto *P)
   lock->addr = p->cf->remote_ip;    lock->addr = p->cf->remote_ip;
   lock->port = p->cf->remote_port;    lock->port = p->cf->remote_port;
   lock->iface = p->cf->iface;    lock->iface = p->cf->iface;
     lock->vrf = p->cf->iface ? NULL : p->p.vrf;
   lock->type = OBJLOCK_TCP;    lock->type = OBJLOCK_TCP;
   lock->hook = bgp_start_locked;    lock->hook = bgp_start_locked;
   lock->data = p;    lock->data = p;
Line 1194  static int Line 1261  static int
 bgp_shutdown(struct proto *P)  bgp_shutdown(struct proto *P)
 {  {
   struct bgp_proto *p = (struct bgp_proto *) P;    struct bgp_proto *p = (struct bgp_proto *) P;
  unsigned subcode = 0;  uint subcode = 0;
   
     char *message = NULL;
     byte *data = NULL;
     uint len = 0;
   
   BGP_TRACE(D_EVENTS, "Shutdown requested");    BGP_TRACE(D_EVENTS, "Shutdown requested");
   
   switch (P->down_code)    switch (P->down_code)
Line 1212  bgp_shutdown(struct proto *P) Line 1283  bgp_shutdown(struct proto *P)
     case PDC_CMD_DISABLE:      case PDC_CMD_DISABLE:
     case PDC_CMD_SHUTDOWN:      case PDC_CMD_SHUTDOWN:
       subcode = 2; // Errcode 6, 2 - administrative shutdown        subcode = 2; // Errcode 6, 2 - administrative shutdown
         message = P->message;
       break;        break;
   
     case PDC_CMD_RESTART:      case PDC_CMD_RESTART:
       subcode = 4; // Errcode 6, 4 - administrative reset        subcode = 4; // Errcode 6, 4 - administrative reset
         message = P->message;
       break;        break;
   
     case PDC_RX_LIMIT_HIT:      case PDC_RX_LIMIT_HIT:
Line 1240  bgp_shutdown(struct proto *P) Line 1313  bgp_shutdown(struct proto *P)
   bgp_store_error(p, NULL, BE_MAN_DOWN, 0);    bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
   p->startup_delay = 0;    p->startup_delay = 0;
   
 done:  /* RFC 8203 - shutdown communication */
  bgp_stop(p, subcode);  if (message)
   {
     uint msg_len = strlen(message);
     msg_len = MIN(msg_len, 255);
 
     /* Buffer will be freed automatically by protocol shutdown */
     data = mb_alloc(p->p.pool, msg_len + 1);
     len = msg_len + 1;
 
     data[0] = msg_len;
     memcpy(data+1, message, msg_len);
   }
 
 done:
   bgp_stop(p, subcode, data, len);
   return p->p.proto_state;    return p->p.proto_state;
 }  }
   
Line 1275  bgp_init(struct proto_config *C) Line 1362  bgp_init(struct proto_config *C)
   P->rte_better = bgp_rte_better;    P->rte_better = bgp_rte_better;
   P->rte_mergable = bgp_rte_mergable;    P->rte_mergable = bgp_rte_mergable;
   P->rte_recalculate = c->deterministic_med ? bgp_rte_recalculate : NULL;    P->rte_recalculate = c->deterministic_med ? bgp_rte_recalculate : NULL;
     P->rte_modify = bgp_rte_modify_stale;
   
   p->cf = c;    p->cf = c;
   p->local_as = c->local_as;    p->local_as = c->local_as;
Line 1310  bgp_check_config(struct bgp_config *c) Line 1398  bgp_check_config(struct bgp_config *c)
   if (!c->missing_lladdr)    if (!c->missing_lladdr)
     c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;      c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;
   
     /* LLGR mode default based on GR mode */
     if (c->llgr_mode < 0)
       c->llgr_mode = c->gr_mode ? BGP_LLGR_AWARE : 0;
   
   /* Disable after error incompatible with restart limit action */    /* Disable after error incompatible with restart limit action */
   if (c->c.in_limit && (c->c.in_limit->action == PLA_RESTART) && c->disable_after_error)    if (c->c.in_limit && (c->c.in_limit->action == PLA_RESTART) && c->disable_after_error)
     c->c.in_limit->action = PLA_DISABLE;      c->c.in_limit->action = PLA_DISABLE;
Line 1324  bgp_check_config(struct bgp_config *c) Line 1416  bgp_check_config(struct bgp_config *c)
   if (!c->remote_as)    if (!c->remote_as)
     cf_error("Remote AS number must be set");      cf_error("Remote AS number must be set");
   
  // if (ipa_is_link_local(c->remote_ip) && !c->iface)  if (ipa_is_link_local(c->remote_ip) && !c->iface)
  //   cf_error("Link-local neighbor address requires specified interface");    cf_error("Link-local neighbor address requires specified interface");
   
   if (!ipa_is_link_local(c->remote_ip) != !c->iface)  
     cf_error("Link-local address and interface scope must be used together");  
   
   if (!(c->capabilities && c->enable_as4) && (c->remote_as > 0xFFFF))    if (!(c->capabilities && c->enable_as4) && (c->remote_as > 0xFFFF))
     cf_error("Neighbor AS number out of range (AS4 not available)");      cf_error("Neighbor AS number out of range (AS4 not available)");
   
Line 1346  bgp_check_config(struct bgp_config *c) Line 1435  bgp_check_config(struct bgp_config *c)
                       ipa_is_link_local(c->source_addr)))                        ipa_is_link_local(c->source_addr)))
     cf_error("Multihop BGP cannot be used with link-local addresses");      cf_error("Multihop BGP cannot be used with link-local addresses");
   
     if (c->multihop && c->iface)
       cf_error("Multihop BGP cannot be bound to interface");
   
   if (c->multihop && c->check_link)    if (c->multihop && c->check_link)
     cf_error("Multihop BGP cannot depend on link state");      cf_error("Multihop BGP cannot depend on link state");
   
Line 1360  bgp_check_config(struct bgp_config *c) Line 1452  bgp_check_config(struct bgp_config *c)
   
   if (c->secondary && !c->c.table->sorted)    if (c->secondary && !c->c.table->sorted)
     cf_error("BGP with secondary option requires sorted table");      cf_error("BGP with secondary option requires sorted table");
   
     if (!c->gr_mode && c->llgr_mode)
       cf_error("Long-lived graceful restart requires basic graceful restart");
 }  }
   
 static int  static int
Line 1431  bgp_error(struct bgp_conn *c, unsigned code, unsigned  Line 1526  bgp_error(struct bgp_conn *c, unsigned code, unsigned 
   if (code != 6)    if (code != 6)
     {      {
       bgp_update_startup_delay(p);        bgp_update_startup_delay(p);
      bgp_stop(p, 0);      bgp_stop(p, 0, NULL, 0);
     }      }
 }  }
   
Line 1528  bgp_show_proto_info(struct proto *P) Line 1623  bgp_show_proto_info(struct proto *P)
   if (p->gr_active)    if (p->gr_active)
     cli_msg(-1006, "    Neighbor graceful restart active");      cli_msg(-1006, "    Neighbor graceful restart active");
   
     if (p->gr_active && p->gr_timer->expires)
       cli_msg(-1006, "    %-15s   %d/-",
               (p->gr_active != BGP_GRS_LLGR_2) ? "Restart timer:" : "LL stale timer:",
               p->gr_timer->expires - now);
   
   if (P->proto_state == PS_START)    if (P->proto_state == PS_START)
     {      {
       struct bgp_conn *oc = &p->outgoing_conn;        struct bgp_conn *oc = &p->outgoing_conn;
Line 1541  bgp_show_proto_info(struct proto *P) Line 1641  bgp_show_proto_info(struct proto *P)
           (oc->connect_retry_timer->expires))            (oc->connect_retry_timer->expires))
         cli_msg(-1006, "    Connect delay:    %d/%d",          cli_msg(-1006, "    Connect delay:    %d/%d",
                 oc->connect_retry_timer->expires - now, p->cf->connect_delay_time);                  oc->connect_retry_timer->expires - now, p->cf->connect_delay_time);
   
       if (p->gr_active && p->gr_timer->expires)  
         cli_msg(-1006, "    Restart timer:    %d/-", p->gr_timer->expires - now);  
     }      }
   else if (P->proto_state == PS_UP)    else if (P->proto_state == PS_UP)
     {      {
Line 1552  bgp_show_proto_info(struct proto *P) Line 1649  bgp_show_proto_info(struct proto *P)
               c->peer_refresh_support ? " refresh" : "",                c->peer_refresh_support ? " refresh" : "",
               c->peer_enhanced_refresh_support ? " enhanced-refresh" : "",                c->peer_enhanced_refresh_support ? " enhanced-refresh" : "",
               c->peer_gr_able ? " restart-able" : (c->peer_gr_aware ? " restart-aware" : ""),                c->peer_gr_able ? " restart-able" : (c->peer_gr_aware ? " restart-aware" : ""),
                 c->peer_llgr_able ? " llgr-able" : (c->peer_llgr_aware ? " llgr-aware" : ""),
               c->peer_as4_support ? " AS4" : "",                c->peer_as4_support ? " AS4" : "",
               (c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "",                (c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "",
               (c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "",                (c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "",

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>