📄 bgp_packet.c
字号:
/* Unfeasible Routes Length. */; cp = stream_get_putp (s); stream_putw (s, 0); /* Withdrawn Routes. */ if (p.family == AF_INET && safi == SAFI_UNICAST) { stream_put_prefix (s, &p); unfeasible_len = stream_get_putp (s) - cp - 2; /* Set unfeasible len. */ stream_putw_at (s, cp, unfeasible_len); /* Set total path attribute length. */ stream_putw (s, 0); } else { pos = stream_get_putp (s); stream_putw (s, 0); total_attr_len = bgp_packet_withdraw (peer, s, &p, afi, safi, NULL, NULL); /* Set total path attribute length. */ stream_putw_at (s, pos, total_attr_len); } bgp_packet_set_size (s); packet = bgp_packet_dup (s); stream_free (s); /* Add packet to the peer. */ bgp_packet_add (peer, packet); BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}/* Get next packet to be written. */struct stream *bgp_write_packet (struct peer *peer){ afi_t afi; safi_t safi; struct stream *s = NULL; struct bgp_advertise *adv; s = stream_fifo_head (peer->obuf); if (s) return s; for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw); if (adv) { s = bgp_withdraw_packet (peer, afi, safi); if (s) return s; } } for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { adv = FIFO_HEAD (&peer->sync[afi][safi]->update); if (adv) { if (adv->binfo && adv->binfo->uptime < peer->synctime[afi][safi]) { if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV) && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV) && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE) && safi != SAFI_MPLS_VPN) { if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) s = bgp_update_packet (peer, afi, safi); } else s = bgp_update_packet (peer, afi, safi); } if (s) return s; } if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV)) { if (peer->afc_nego[afi][safi] && peer->synctime[afi][safi] && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND) && safi != SAFI_MPLS_VPN) { SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND); return bgp_update_packet_eor (peer, afi, safi); } } } return NULL;}/* Is there partially written packet or updates we can send right now. */intbgp_write_proceed (struct peer *peer){ afi_t afi; safi_t safi; struct bgp_advertise *adv; if (stream_fifo_head (peer->obuf)) return 1; for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) return 1; for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL) if (adv->binfo->uptime < peer->synctime[afi][safi]) return 1; return 0;}/* Write packet to the peer. */intbgp_write (struct thread *thread){ struct peer *peer; u_char type; struct stream *s; int num; int count = 0; int write_errno; /* Yes first of all get peer pointer. */ peer = THREAD_ARG (thread); peer->t_write = NULL; /* For non-blocking IO check. */ if (peer->status == Connect) { bgp_connect_check (peer); return 0; } /* Nonblocking write until TCP output buffer is full. */ while (1) { int writenum; s = bgp_write_packet (peer); if (! s) return 0; /* Number of bytes to be sent. */ writenum = stream_get_endp (s) - stream_get_getp (s); /* Call write() system call. */ num = write (peer->fd, STREAM_PNT (s), writenum); write_errno = errno; if (num <= 0) { /* Partial write. */ if (write_errno == EWOULDBLOCK || write_errno == EAGAIN) break; bgp_stop (peer); peer->status = Idle; bgp_timer_set (peer); return 0; } if (num != writenum) { stream_forward (s, num); if (write_errno == EAGAIN) break; continue; } /* Retrieve BGP packet type. */ stream_set_getp (s, BGP_MARKER_SIZE + 2); type = stream_getc (s); switch (type) { case BGP_MSG_OPEN: peer->open_out++; break; case BGP_MSG_UPDATE: peer->update_out++; break; case BGP_MSG_NOTIFY: peer->notify_out++; /* BGP_EVENT_ADD (peer, BGP_Stop); */ bgp_stop_with_error (peer); bgp_fsm_change_status (peer, Idle); bgp_timer_set (peer); return 0; break; case BGP_MSG_KEEPALIVE: peer->keepalive_out++; break; case BGP_MSG_ROUTE_REFRESH_NEW: case BGP_MSG_ROUTE_REFRESH_OLD: peer->refresh_out++; break; case BGP_MSG_CAPABILITY: peer->dynamic_cap_out++; break; } /* OK we send packet so delete it. */ bgp_packet_delete (peer); if (++count >= BGP_WRITE_PACKET_MAX) break; } if (bgp_write_proceed (peer)) BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); return 0;}/* This is only for sending NOTIFICATION message to neighbor. */intbgp_write_notify (struct peer *peer){ int ret; u_char type; struct stream *s; /* There should be at least one packet. */ s = stream_fifo_head (peer->obuf); if (!s) return 0; assert (stream_get_endp (s) >= BGP_HEADER_SIZE); /* I'm not sure fd is writable. */ ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s)); if (ret <= 0) { bgp_stop (peer); peer->status = Idle; bgp_timer_set (peer); return 0; } /* Retrieve BGP packet type. */ stream_set_getp (s, BGP_MARKER_SIZE + 2); type = stream_getc (s); assert (type == BGP_MSG_NOTIFY); /* Type should be notify. */ peer->notify_out++; /* We don't call event manager at here for avoiding other events. */ if (peer->status == Established) bgp_stop (peer); else { bgp_stop_with_error (peer); bgp_fsm_change_status (peer, Idle); } bgp_timer_set (peer); return 0;}/* Make keepalive packet and send it to the peer. */voidbgp_keepalive_send (struct peer *peer){ struct stream *s; int length; s = stream_new (BGP_MAX_PACKET_SIZE); /* Make keepalive packet. */ bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE); /* Set packet size. */ length = bgp_packet_set_size (s); /* Dump packet if debug option is set. */ /* bgp_packet_dump (s); */ if (BGP_DEBUG (keepalive, KEEPALIVE)) zlog_info ("%s sending KEEPALIVE", peer->host); if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s send message type %d, length (incl. header) %d", peer->host, BGP_MSG_KEEPALIVE, length); /* Add packet to the peer. */ bgp_packet_add (peer, s); BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}/* Make open packet and send it to the peer. */voidbgp_open_send (struct peer *peer){ struct stream *s; int length; u_int16_t send_holdtime; as_t local_as; if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) send_holdtime = peer->holdtime; else send_holdtime = peer->bgp->default_holdtime; /* local-as Change */ if (peer->change_local_as) local_as = peer->change_local_as; else local_as = peer->local_as; s = stream_new (BGP_MAX_PACKET_SIZE); /* Make open packet. */ bgp_packet_set_marker (s, BGP_MSG_OPEN); /* Set open packet values. */ stream_putc (s, BGP_VERSION_4); /* BGP version */ stream_putw (s, local_as); /* My Autonomous System*/ stream_putw (s, send_holdtime); /* Hold Time */ stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */ /* Set capability code. */ bgp_open_capability (s, peer); /* Set BGP packet length. */ length = bgp_packet_set_size (s); if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s sending OPEN, version %d, my as %d, holdtime %d, id %s", peer->host, BGP_VERSION_4, local_as, send_holdtime, inet_ntoa (peer->local_id)); if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s send message type %d, length (incl. header) %d", peer->host, BGP_MSG_OPEN, length); /* Dump packet if debug option is set. */ /* bgp_packet_dump (s); */ /* Add packet to the peer. */ bgp_packet_add (peer, s); BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);}/* Send BGP notify packet with data potion. */voidbgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code, u_char *data, size_t datalen){ struct stream *s; int length; /* Allocate new stream. */ s = stream_new (BGP_MAX_PACKET_SIZE); /* Make nitify packet. */ bgp_packet_set_marker (s, BGP_MSG_NOTIFY); /* Set notify packet values. */ stream_putc (s, code); /* BGP notify code */ stream_putc (s, sub_code); /* BGP notify sub_code */ /* If notify data is present. */ if (data) stream_write (s, data, datalen); /* Set BGP packet length. */ length = bgp_packet_set_size (s); /* Add packet to the peer. */ stream_fifo_clean (peer->obuf); bgp_packet_add (peer, s); /* For debug */ { struct bgp_notify bgp_notify; int first = 0; int i; char c[4]; bgp_notify.code = code; bgp_notify.subcode = sub_code; bgp_notify.data = NULL; bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE; if (bgp_notify.length) { bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3); for (i = 0; i < bgp_notify.length; i++) if (first) { sprintf (c, " %02x", data[i]); strcat (bgp_notify.data, c); } else { first = 1; sprintf (c, "%02x", data[i]); strcpy (bgp_notify.data, c); } } bgp_notify_print (peer, &bgp_notify, "sending"); if (bgp_notify.data) XFREE (MTYPE_TMP, bgp_notify.data); } if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s send message type %d, length (incl. header) %d", peer->host, BGP_MSG_NOTIFY, length); /* peer reset cause */ if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE) { if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET) peer->last_reset = PEER_DOWN_USER_RESET; else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN) peer->last_reset = PEER_DOWN_USER_SHUTDOWN; else if (sub_code == BGP_NOTIFY_CEASE_PEER_UNCONFIG) peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; else peer->last_reset = PEER_DOWN_NOTIFY_SEND; } /* Call imidiately. */ BGP_WRITE_OFF (peer->t_write); bgp_write_notify (peer);}/* Send BGP notify packet. */voidbgp_notify_send (struct peer *peer, u_char code, u_char sub_code){ bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);}char *afi2str (afi_t afi){ if (afi == AFI_IP) return "AFI_IP"; else if (afi == AFI_IP6) return "AFI_IP6"; else return "Unknown AFI";}char *safi2str (safi_t safi){ if (safi == SAFI_UNICAST) return "SAFI_UNICAST"; else if (safi == SAFI_MULTICAST) return "SAFI_MULTICAST"; else if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPNV4) return "SAFI_MPLS_VPN"; else return "Unknown SAFI";}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -