Skip to content

Commit 94e65ba

Browse files
authored
Merge pull request #18789 from vjardin/vj_addbgpiptransparent
bgpd: add neighbor ip-transparent
2 parents 887fab3 + 4d07a2f commit 94e65ba

File tree

9 files changed

+364
-0
lines changed

9 files changed

+364
-0
lines changed

bgpd/bgp_network.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,14 @@ enum connect_result bgp_connect(struct peer_connection *connection)
828828
if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS))
829829
sockopt_tcp_mss_set(connection->fd, peer->tcp_mss);
830830

831+
/* Neighbor's bind() as a source address when ip transparent is used */
832+
if (CHECK_FLAG(peer->flags, PEER_FLAG_IP_TRANSPARENT) &&
833+
CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE)) {
834+
frr_with_privs (&bgpd_privs) {
835+
sockopt_ip_transparent(connection->fd);
836+
}
837+
}
838+
831839
bgp_socket_set_buffer_size(connection->fd);
832840

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

916924
if (!bgp_zebra_nexthop_set(connection->su_local, connection->su_remote, &peer->nexthop,
917925
peer)) {
926+
/* no nexthop, but the admin has enforced the source address with an ip-transparent mode
927+
* so let's honor the configuration.
928+
*/
929+
if (CHECK_FLAG(peer->flags, PEER_FLAG_IP_TRANSPARENT) &&
930+
CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE))
931+
return 0;
918932
flog_err(EC_BGP_NH_UPD,
919933
"%s: nexthop_set failed, local: %pSUp remote: %pSUp update_if: %s resetting connection - intf %s",
920934
peer->host, connection->su_local, connection->su_remote,

bgpd/bgp_vty.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18427,6 +18427,34 @@ DEFUN(no_neighbor_tcp_mss, no_neighbor_tcp_mss_cmd,
1842718427
return peer_tcp_mss_vty(vty, argv[peer_index]->arg, NULL);
1842818428
}
1842918429

18430+
DEFPY(neighbor_ip_transparent,
18431+
neighbor_ip_transparent_cmd,
18432+
"[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor ip-transparent",
18433+
NO_STR
18434+
NEIGHBOR_STR
18435+
NEIGHBOR_ADDR_STR2
18436+
"Enable IP_TRANSPARENT on the BGP TCP socket\n")
18437+
{
18438+
struct peer *peer;
18439+
int ret;
18440+
18441+
peer = peer_and_group_lookup_vty(vty, neighbor);
18442+
if (!peer)
18443+
return CMD_WARNING_CONFIG_FAILED;
18444+
18445+
if (!peergroup_flag_check(peer, PEER_FLAG_UPDATE_SOURCE)) {
18446+
vty_out(vty, "%% Missing update-source\n");
18447+
return CMD_WARNING_CONFIG_FAILED;
18448+
}
18449+
18450+
if (no)
18451+
ret = peer_flag_unset_vty(vty, neighbor, PEER_FLAG_IP_TRANSPARENT);
18452+
else
18453+
ret = peer_flag_set_vty(vty, neighbor, PEER_FLAG_IP_TRANSPARENT);
18454+
18455+
return bgp_vty_return(vty, ret);
18456+
}
18457+
1843018458
DEFPY(bgp_retain_route_target, bgp_retain_route_target_cmd,
1843118459
"[no$no] bgp retain route-target all",
1843218460
NO_STR BGP_STR
@@ -19027,6 +19055,10 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
1902719055
peer->update_if);
1902819056
}
1902919057

19058+
/* ip-transparent on/off */
19059+
if (peergroup_flag_check(peer, PEER_FLAG_IP_TRANSPARENT))
19060+
vty_out(vty, " neighbor %s ip-transparent\n", addr);
19061+
1903019062
/* advertisement-interval */
1903119063
if (peergroup_flag_check(peer, PEER_FLAG_ROUTEADV))
1903219064
vty_out(vty, " neighbor %s advertisement-interval %u\n", addr,
@@ -22220,6 +22252,8 @@ void bgp_vty_init(void)
2222022252
install_element(BGP_NODE, &neighbor_tcp_mss_cmd);
2222122253
install_element(BGP_NODE, &no_neighbor_tcp_mss_cmd);
2222222254

22255+
install_element(BGP_NODE, &neighbor_ip_transparent_cmd);
22256+
2222322257
/* srv6 commands */
2222422258
install_element(VIEW_NODE, &show_bgp_srv6_cmd);
2222522259
install_element(BGP_NODE, &bgp_segment_routing_srv6_cmd);

bgpd/bgpd.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4979,6 +4979,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
49794979
{PEER_FLAG_CAPABILITY_LINK_LOCAL, 0, peer_change_none},
49804980
{PEER_FLAG_BFD_STRICT, 0, peer_change_none},
49814981
{PEER_FLAG_SEND_NHC_ATTRIBUTE, 0, peer_change_none},
4982+
{PEER_FLAG_IP_TRANSPARENT, 0, peer_change_reset},
49824983
{0, 0, 0}};
49834984

49844985
static const struct peer_flag_action peer_af_flag_action_list[] = {

bgpd/bgpd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,7 @@ struct peer {
17031703
#define PEER_FLAG_BFD_STRICT (1ULL << 43)
17041704
/* https://datatracker.ietf.org/doc/html/draft-ietf-idr-entropy-label */
17051705
#define PEER_FLAG_SEND_NHC_ATTRIBUTE (1ULL << 44)
1706+
#define PEER_FLAG_IP_TRANSPARENT (1ULL << 45) /* ip-transparent */
17061707

17071708
/*
17081709
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART

doc/user/bgp.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,15 @@ Configuring Peers
17661766
neighbor foo update-source 192.168.0.1
17671767
neighbor bar update-source lo0
17681768
1769+
.. clicmd:: neighbor PEER ip-transparent
1770+
1771+
Use this command when you need to establish a BGP session with a
1772+
neighbor using an IP address that you do *not* own. Some typical use
1773+
cases include running BGP in a container without configuring the
1774+
address on a loopback interface, peering over a virtual (floating)
1775+
IP (VIP), or operating as a transparent IP firewall.
1776+
The BGP TCP session shall have a TCP source address that you set with
1777+
`neighbor PEER update-source A.B.C.D`.
17691778

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

lib/sockopt.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,3 +743,21 @@ int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
743743
return 0;
744744
#endif
745745
}
746+
747+
/* set IP_TRANSPARENT to socket */
748+
void sockopt_ip_transparent(int sock)
749+
{
750+
int err = -1;
751+
752+
#if defined(IP_TRANSPARENT)
753+
const char flag_on = 1;
754+
755+
err = setsockopt(sock, SOL_IP, IP_TRANSPARENT, &flag_on, sizeof(flag_on));
756+
#else
757+
err = ENOPROTOOPT;
758+
#endif
759+
if (err < 0) {
760+
flog_err_sys(EC_LIB_SYSTEM_CALL, "%s failed: setsockopt(%d, IP_TRANSPARENT): %s",
761+
__func__, sock, safe_strerror(errno));
762+
}
763+
}

lib/sockopt.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ extern int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
170170
uint16_t keepalive_intvl,
171171
uint16_t keepalive_probes);
172172

173+
/*
174+
* Set IP_TRANSPARENT option to socket
175+
*
176+
* sock
177+
* Socket to enable option on.
178+
*/
179+
extern void sockopt_ip_transparent(int sock);
180+
173181
#ifdef __cplusplus
174182
}
175183
#endif
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"routers": {
3+
"r1": {
4+
"links": {
5+
"lo": { "type": "loopback" },
6+
"r2": { "ipv4": "10.20.100.1/24"}
7+
},
8+
"static_routes": [
9+
{"network": "0.0.0.0/0", "next_hop": "10.20.100.2"}
10+
],
11+
"bgp": { "local_as": "20101" }
12+
},
13+
"r2": {
14+
"links": {
15+
"lo": { "type": "loopback" },
16+
"r1": { "ipv4": "10.20.100.2/24"}
17+
},
18+
"bgp": { "local_as": "20102" }
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)