Skip to content

bgpd: add neighbor ip-transparent #18789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions bgpd/bgp_network.c
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,14 @@ enum connect_result bgp_connect(struct peer_connection *connection)
if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS))
sockopt_tcp_mss_set(connection->fd, peer->tcp_mss);

/* Neighbor's bind() as a source address when ip transparent is used */
if (CHECK_FLAG(peer->flags, PEER_FLAG_IP_TRANSPARENT) &&
CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE)) {
frr_with_privs (&bgpd_privs) {
sockopt_ip_transparent(connection->fd);
}
}

bgp_socket_set_buffer_size(connection->fd);

/* Set TCP keepalive when TCP keepalive is enabled */
Expand Down Expand Up @@ -915,6 +923,12 @@ int bgp_getsockname(struct peer_connection *connection)

if (!bgp_zebra_nexthop_set(connection->su_local, connection->su_remote, &peer->nexthop,
peer)) {
/* no nexthop, but the admin has enforced the source address with an ip-transparent mode
* so let's honor the configuration.
*/
if (CHECK_FLAG(peer->flags, PEER_FLAG_IP_TRANSPARENT) &&
CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE))
return 0;
flog_err(EC_BGP_NH_UPD,
"%s: nexthop_set failed, local: %pSUp remote: %pSUp update_if: %s resetting connection - intf %s",
peer->host, connection->su_local, connection->su_remote,
Expand Down
34 changes: 34 additions & 0 deletions bgpd/bgp_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -18427,6 +18427,34 @@ DEFUN(no_neighbor_tcp_mss, no_neighbor_tcp_mss_cmd,
return peer_tcp_mss_vty(vty, argv[peer_index]->arg, NULL);
}

DEFPY(neighbor_ip_transparent,
neighbor_ip_transparent_cmd,
"[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor ip-transparent",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Enable IP_TRANSPARENT on the BGP TCP socket\n")
{
struct peer *peer;
int ret;

peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;

if (!peergroup_flag_check(peer, PEER_FLAG_UPDATE_SOURCE)) {
vty_out(vty, "%% Missing update-source\n");
return CMD_WARNING_CONFIG_FAILED;
}

if (no)
ret = peer_flag_unset_vty(vty, neighbor, PEER_FLAG_IP_TRANSPARENT);
else
ret = peer_flag_set_vty(vty, neighbor, PEER_FLAG_IP_TRANSPARENT);

return bgp_vty_return(vty, ret);
}

DEFPY(bgp_retain_route_target, bgp_retain_route_target_cmd,
"[no$no] bgp retain route-target all",
NO_STR BGP_STR
Expand Down Expand Up @@ -19027,6 +19055,10 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
peer->update_if);
}

/* ip-transparent on/off */
if (peergroup_flag_check(peer, PEER_FLAG_IP_TRANSPARENT))
vty_out(vty, " neighbor %s ip-transparent\n", addr);

/* advertisement-interval */
if (peergroup_flag_check(peer, PEER_FLAG_ROUTEADV))
vty_out(vty, " neighbor %s advertisement-interval %u\n", addr,
Expand Down Expand Up @@ -22220,6 +22252,8 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &neighbor_tcp_mss_cmd);
install_element(BGP_NODE, &no_neighbor_tcp_mss_cmd);

install_element(BGP_NODE, &neighbor_ip_transparent_cmd);

/* srv6 commands */
install_element(VIEW_NODE, &show_bgp_srv6_cmd);
install_element(BGP_NODE, &bgp_segment_routing_srv6_cmd);
Expand Down
1 change: 1 addition & 0 deletions bgpd/bgpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -4979,6 +4979,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_CAPABILITY_LINK_LOCAL, 0, peer_change_none},
{PEER_FLAG_BFD_STRICT, 0, peer_change_none},
{PEER_FLAG_SEND_NHC_ATTRIBUTE, 0, peer_change_none},
{PEER_FLAG_IP_TRANSPARENT, 0, peer_change_reset},
{0, 0, 0}};

static const struct peer_flag_action peer_af_flag_action_list[] = {
Expand Down
1 change: 1 addition & 0 deletions bgpd/bgpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,7 @@ struct peer {
#define PEER_FLAG_BFD_STRICT (1ULL << 43)
/* https://datatracker.ietf.org/doc/html/draft-ietf-idr-entropy-label */
#define PEER_FLAG_SEND_NHC_ATTRIBUTE (1ULL << 44)
#define PEER_FLAG_IP_TRANSPARENT (1ULL << 45) /* ip-transparent */

/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
Expand Down
9 changes: 9 additions & 0 deletions doc/user/bgp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,15 @@ Configuring Peers
neighbor foo update-source 192.168.0.1
neighbor bar update-source lo0

.. clicmd:: neighbor PEER ip-transparent

Use this command when you need to establish a BGP session with a
neighbor using an IP address that you do *not* own. Some typical use
cases include running BGP in a container without configuring the
address on a loopback interface, peering over a virtual (floating)
IP (VIP), or operating as a transparent IP firewall.
The BGP TCP session shall have a TCP source address that you set with
`neighbor PEER update-source A.B.C.D`.

.. clicmd:: neighbor PEER default-originate [route-map WORD]

Expand Down
18 changes: 18 additions & 0 deletions lib/sockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,3 +743,21 @@ int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
return 0;
#endif
}

/* set IP_TRANSPARENT to socket */
void sockopt_ip_transparent(int sock)
{
int err = -1;

#if defined(IP_TRANSPARENT)
const char flag_on = 1;

err = setsockopt(sock, SOL_IP, IP_TRANSPARENT, &flag_on, sizeof(flag_on));
#else
err = ENOPROTOOPT;
#endif
if (err < 0) {
flog_err_sys(EC_LIB_SYSTEM_CALL, "%s failed: setsockopt(%d, IP_TRANSPARENT): %s",
__func__, sock, safe_strerror(errno));
}
}
8 changes: 8 additions & 0 deletions lib/sockopt.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ extern int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
uint16_t keepalive_intvl,
uint16_t keepalive_probes);

/*
* Set IP_TRANSPARENT option to socket
*
* sock
* Socket to enable option on.
*/
extern void sockopt_ip_transparent(int sock);

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"routers": {
"r1": {
"links": {
"lo": { "type": "loopback" },
"r2": { "ipv4": "10.20.100.1/24"}
},
"static_routes": [
{"network": "0.0.0.0/0", "next_hop": "10.20.100.2"}
],
"bgp": { "local_as": "20101" }
},
"r2": {
"links": {
"lo": { "type": "loopback" },
"r1": { "ipv4": "10.20.100.2/24"}
},
"bgp": { "local_as": "20102" }
}
}
}
Loading
Loading