Better handle IPv6 routes advertisement (non-)support.
Don't try to enable multiprotocol BGP when the peer says it can't. Signed-off-by: Benjamin Cama <benoar@dolka.fr>
This commit is contained in:
parent
7407c1a1c4
commit
e86393ea90
2 changed files with 39 additions and 18 deletions
49
bgp.c
49
bgp.c
|
|
@ -295,6 +295,8 @@ int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive,
|
||||||
BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE);
|
BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peer->mp_handling = HandlingUnknown;
|
||||||
|
|
||||||
LOG(4, 0, 0, "Initiating BGP connection to %s (routing %s)\n",
|
LOG(4, 0, 0, "Initiating BGP connection to %s (routing %s)\n",
|
||||||
name, enable ? "enabled" : "suspended");
|
name, enable ? "enabled" : "suspended");
|
||||||
|
|
||||||
|
|
@ -967,8 +969,6 @@ static int bgp_connect(struct bgp_peer *peer)
|
||||||
|
|
||||||
LOG(4, 0, 0, "BGP peer %s: state Active\n", inet_ntoa(addr.sin_addr));
|
LOG(4, 0, 0, "BGP peer %s: state Active\n", inet_ntoa(addr.sin_addr));
|
||||||
|
|
||||||
peer->handle_ipv6_routes = 0;
|
|
||||||
|
|
||||||
return bgp_send_open(peer);
|
return bgp_send_open(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -992,8 +992,6 @@ static int bgp_handle_connect(struct bgp_peer *peer)
|
||||||
|
|
||||||
LOG(4, 0, 0, "BGP peer %s: state Active\n", peer->name);
|
LOG(4, 0, 0, "BGP peer %s: state Active\n", peer->name);
|
||||||
|
|
||||||
peer->handle_ipv6_routes = 0;
|
|
||||||
|
|
||||||
return bgp_send_open(peer);
|
return bgp_send_open(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1260,7 +1258,7 @@ static int bgp_handle_input(struct bgp_peer *peer)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer->handle_ipv6_routes = 1;
|
peer->mp_handling = HandleIPv6Routes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1298,6 +1296,15 @@ static int bgp_handle_input(struct bgp_peer *peer)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notification->error_code == BGP_ERR_OPEN
|
||||||
|
&& notification->error_subcode == BGP_ERR_OPN_UNSUP_PARAM)
|
||||||
|
{
|
||||||
|
LOG(4, 0, 0, "BGP peer %s doesn't support BGP Capabilities\n", peer->name);
|
||||||
|
peer->mp_handling = DoesntHandleIPv6Routes;
|
||||||
|
bgp_restart(peer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (notification->error_code == BGP_ERR_OPEN
|
if (notification->error_code == BGP_ERR_OPEN
|
||||||
&& notification->error_subcode == BGP_ERR_OPN_UNSUP_CAP)
|
&& notification->error_subcode == BGP_ERR_OPN_UNSUP_CAP)
|
||||||
{
|
{
|
||||||
|
|
@ -1305,7 +1312,7 @@ static int bgp_handle_input(struct bgp_peer *peer)
|
||||||
an "unsupported capability" message, we disable IPv6 routes for
|
an "unsupported capability" message, we disable IPv6 routes for
|
||||||
this peer */
|
this peer */
|
||||||
LOG(4, 0, 0, "BGP peer %s doesn't support IPv6 routes advertisement\n", peer->name);
|
LOG(4, 0, 0, "BGP peer %s doesn't support IPv6 routes advertisement\n", peer->name);
|
||||||
peer->handle_ipv6_routes = 0;
|
peer->mp_handling = DoesntHandleIPv6Routes;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1354,20 +1361,28 @@ static int bgp_send_open(struct bgp_peer *peer)
|
||||||
data.hold_time = htons(peer->hold);
|
data.hold_time = htons(peer->hold);
|
||||||
data.identifier = my_address;
|
data.identifier = my_address;
|
||||||
|
|
||||||
/* construct the param and capability */
|
/* if we know peer doesn't support MP (mp_handling == DoesntHandleIPv6Routes)
|
||||||
cap_mp_ipv6.code = BGP_CAP_CODE_MP;
|
then don't add this parameter */
|
||||||
cap_mp_ipv6.len = sizeof(mp_ipv6);
|
if (peer->mp_handling == HandlingUnknown
|
||||||
memcpy(&cap_mp_ipv6.value, &mp_ipv6, cap_mp_ipv6.len);
|
|| peer->mp_handling == HandleIPv6Routes)
|
||||||
|
{
|
||||||
|
/* construct the param and capability */
|
||||||
|
cap_mp_ipv6.code = BGP_CAP_CODE_MP;
|
||||||
|
cap_mp_ipv6.len = sizeof(mp_ipv6);
|
||||||
|
memcpy(&cap_mp_ipv6.value, &mp_ipv6, cap_mp_ipv6.len);
|
||||||
|
|
||||||
param_cap_mp_ipv6.type = BGP_PARAM_TYPE_CAPABILITY;
|
param_cap_mp_ipv6.type = BGP_PARAM_TYPE_CAPABILITY;
|
||||||
param_cap_mp_ipv6.len = 2 + sizeof(mp_ipv6);
|
param_cap_mp_ipv6.len = 2 + sizeof(mp_ipv6);
|
||||||
memcpy(¶m_cap_mp_ipv6.value, &cap_mp_ipv6, param_cap_mp_ipv6.len);
|
memcpy(¶m_cap_mp_ipv6.value, &cap_mp_ipv6, param_cap_mp_ipv6.len);
|
||||||
|
|
||||||
data.opt_len = 2 + param_cap_mp_ipv6.len;
|
data.opt_len = 2 + param_cap_mp_ipv6.len;
|
||||||
memcpy(&data.opt_params, ¶m_cap_mp_ipv6, data.opt_len);
|
memcpy(&data.opt_params, ¶m_cap_mp_ipv6, data.opt_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data.opt_len = 0;
|
||||||
|
|
||||||
memcpy(peer->outbuf->packet.data, &data, BGP_DATA_OPEN_SIZE);
|
memcpy(peer->outbuf->packet.data, &data, BGP_DATA_OPEN_SIZE + data.opt_len);
|
||||||
len += BGP_DATA_OPEN_SIZE;
|
len += BGP_DATA_OPEN_SIZE + data.opt_len;
|
||||||
|
|
||||||
peer->outbuf->packet.header.len = htons(len);
|
peer->outbuf->packet.header.len = htons(len);
|
||||||
peer->outbuf->done = 0;
|
peer->outbuf->done = 0;
|
||||||
|
|
|
||||||
8
bgp.h
8
bgp.h
|
|
@ -209,6 +209,12 @@ struct bgp_buf {
|
||||||
size_t done; /* bytes sent/recvd */
|
size_t done; /* bytes sent/recvd */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum bgp_mp_handling {
|
||||||
|
HandleIPv6Routes,
|
||||||
|
DoesntHandleIPv6Routes,
|
||||||
|
HandlingUnknown,
|
||||||
|
};
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
struct bgp_peer {
|
struct bgp_peer {
|
||||||
char name[32]; /* peer name */
|
char name[32]; /* peer name */
|
||||||
|
|
@ -237,7 +243,7 @@ struct bgp_peer {
|
||||||
int path_attr_len_without_nexthop; /* length of path attrs without NEXT_HOP */
|
int path_attr_len_without_nexthop; /* length of path attrs without NEXT_HOP */
|
||||||
uint32_t events; /* events to poll */
|
uint32_t events; /* events to poll */
|
||||||
struct event_data edata; /* poll data */
|
struct event_data edata; /* poll data */
|
||||||
int handle_ipv6_routes; /* can handle IPv6 routes advertisements */
|
enum bgp_mp_handling mp_handling; /* how it handles IPv6 routes advertisements */
|
||||||
int update_routes6; /* UPDATE required for IPv6 routes */
|
int update_routes6; /* UPDATE required for IPv6 routes */
|
||||||
struct bgp_route6_list *routes6; /* IPv6 routes known by this peer */
|
struct bgp_route6_list *routes6; /* IPv6 routes known by this peer */
|
||||||
char mp_reach_nlri_partial[BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE];
|
char mp_reach_nlri_partial[BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue