diff --git a/src/bgp/bgp_config.cc b/src/bgp/bgp_config.cc
index 91756ebd885..f0b18f8dbbf 100644
--- a/src/bgp/bgp_config.cc
+++ b/src/bgp/bgp_config.cc
@@ -170,6 +170,8 @@ void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) {
peer_as_ = rhs.peer_as_;
identifier_ = rhs.identifier_;
address_ = rhs.address_;
+ inet_gateway_address_ = rhs.inet_gateway_address_;
+ inet6_gateway_address_ = rhs.inet6_gateway_address_;
port_ = rhs.port_;
source_port_ = rhs.source_port_;
hold_time_ = rhs.hold_time_;
@@ -190,6 +192,8 @@ int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
KEY_COMPARE(peer_as_, rhs.peer_as_);
KEY_COMPARE(identifier_, rhs.identifier_);
KEY_COMPARE(address_, rhs.address_);
+ KEY_COMPARE(inet_gateway_address_, rhs.inet_gateway_address_);
+ KEY_COMPARE(inet6_gateway_address_, rhs.inet6_gateway_address_);
KEY_COMPARE(port_, rhs.port_);
KEY_COMPARE(source_port_, rhs.source_port_);
KEY_COMPARE(hold_time_, rhs.hold_time_);
@@ -203,6 +207,26 @@ int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
BgpFamilyAttributesConfigCompare());
}
+const IpAddress &BgpNeighborConfig::gateway_address(
+ Address::Family family) const {
+ assert(family == Address::INET || family == Address::INET6);
+ if (family == Address::INET) {
+ return inet_gateway_address_;
+ } else {
+ return inet6_gateway_address_;
+ }
+}
+
+void BgpNeighborConfig::set_gateway_address(Address::Family family,
+ const IpAddress &address) {
+ assert(family == Address::INET || family == Address::INET6);
+ if (family == Address::INET) {
+ inet_gateway_address_ = address;
+ } else {
+ inet6_gateway_address_ = address;
+ }
+}
+
BgpNeighborConfig::AddressFamilyList
BgpNeighborConfig::GetAddressFamilies() const {
BgpNeighborConfig::AddressFamilyList family_list;
diff --git a/src/bgp/bgp_config.h b/src/bgp/bgp_config.h
index c43e2cb124e..b580213cd62 100644
--- a/src/bgp/bgp_config.h
+++ b/src/bgp/bgp_config.h
@@ -183,6 +183,9 @@ class BgpNeighborConfig {
return Ip4Address(ntohl(identifier_)).to_string();
}
+ const IpAddress &gateway_address(Address::Family family) const;
+ void set_gateway_address(Address::Family family, const IpAddress &address);
+
uint16_t port() const { return port_; }
void set_port(uint16_t port) { port_ = port; }
@@ -252,6 +255,8 @@ class BgpNeighborConfig {
uint32_t peer_as_;
uint32_t identifier_;
IpAddress address_;
+ IpAddress inet_gateway_address_;
+ IpAddress inet6_gateway_address_;
uint16_t port_;
uint16_t source_port_;
TcpSession::Endpoint remote_endpoint_;
diff --git a/src/bgp/bgp_config_ifmap.cc b/src/bgp/bgp_config_ifmap.cc
index f2d28d3041d..d0c0ee57d80 100644
--- a/src/bgp/bgp_config_ifmap.cc
+++ b/src/bgp/bgp_config_ifmap.cc
@@ -296,14 +296,35 @@ static BgpNeighborConfig *MakeBgpNeighborConfig(
"Invalid peer address " << params.address <<
" for neighbor " << neighbor->name());
}
+
Ip4Address identifier = Ip4Address::from_string(params.identifier, err);
if (err) {
BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_WARN, BGP_LOG_FLAG_ALL,
"Invalid peer identifier " << params.identifier <<
" for neighbor " << neighbor->name());
}
-
neighbor->set_peer_identifier(IpAddressToBgpIdentifier(identifier));
+
+ IpAddress inet_gw_address =
+ Ip4Address::from_string(params.gateway_address, err);
+ if (!params.gateway_address.empty() && err) {
+ BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_WARN, BGP_LOG_FLAG_ALL,
+ "Invalid gateway address " << params.gateway_address <<
+ " for neighbor " << neighbor->name());
+ } else {
+ neighbor->set_gateway_address(Address::INET, inet_gw_address);
+ }
+
+ IpAddress inet6_gw_address =
+ Ip6Address::from_string(params.ipv6_gateway_address, err);
+ if (!params.ipv6_gateway_address.empty() && err) {
+ BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_WARN, BGP_LOG_FLAG_ALL,
+ "Invalid ipv6 gateway address " << params.ipv6_gateway_address <<
+ " for neighbor " << neighbor->name());
+ } else {
+ neighbor->set_gateway_address(Address::INET6, inet6_gw_address);
+ }
+
neighbor->set_port(params.port);
neighbor->set_source_port(params.source_port);
neighbor->set_hold_time(params.hold_time);
diff --git a/src/bgp/bgp_peer.cc b/src/bgp/bgp_peer.cc
index 81213dd8aa2..f649c8c2c96 100644
--- a/src/bgp/bgp_peer.cc
+++ b/src/bgp/bgp_peer.cc
@@ -248,6 +248,11 @@ BgpPeerFamilyAttributes::BgpPeerFamilyAttributes(
loop_count = config->loop_count();
}
prefix_limit = family_config.prefix_limit;
+ if (family_config.family == "inet") {
+ gateway_address = config->gateway_address(Address::INET);
+ } else if (family_config.family == "inet6") {
+ gateway_address = config->gateway_address(Address::INET6);
+ }
}
void BgpPeer::ReceiveEndOfRIB(Address::Family family, size_t msgsize) {
@@ -744,6 +749,12 @@ string BgpPeer::transport_address_string() const {
return oss.str();
}
+string BgpPeer::gateway_address_string(Address::Family family) const {
+ if (!family_attributes_list_[family])
+ return string();
+ return family_attributes_list_[family]->gateway_address.to_string();
+}
+
//
// Customized close routing for BgpPeers.
//
@@ -1702,6 +1713,10 @@ void BgpPeer::FillBgpNeighborFamilyAttributes(BgpNeighborResp *nbr) const {
family_attributes_list_[idx]->loop_count;
show_family_attributes.prefix_limit =
family_attributes_list_[idx]->prefix_limit;
+ if (!family_attributes_list_[idx]->gateway_address.is_unspecified()) {
+ show_family_attributes.gateway_address =
+ family_attributes_list_[idx]->gateway_address.to_string();
+ }
show_family_attributes_list.push_back(show_family_attributes);
}
nbr->set_family_attributes_list(show_family_attributes_list);
diff --git a/src/bgp/bgp_peer.h b/src/bgp/bgp_peer.h
index ea44d3b2c9d..f367867e0dc 100644
--- a/src/bgp/bgp_peer.h
+++ b/src/bgp/bgp_peer.h
@@ -49,6 +49,7 @@ struct BgpPeerFamilyAttributes {
const BgpFamilyAttributesConfig &family_config);
uint8_t loop_count;
uint32_t prefix_limit;
+ IpAddress gateway_address;
};
//
@@ -60,6 +61,7 @@ struct BgpPeerFamilyAttributesCompare {
if (lhs && rhs) {
KEY_COMPARE(lhs->loop_count, rhs->loop_count);
KEY_COMPARE(lhs->prefix_limit, rhs->prefix_limit);
+ KEY_COMPARE(lhs->gateway_address, rhs->gateway_address);
} else {
KEY_COMPARE(lhs, rhs);
}
@@ -141,6 +143,7 @@ class BgpPeer : public IPeer {
const BgpPeerKey &peer_key() const { return peer_key_; }
uint16_t peer_port() const { return peer_port_; }
std::string transport_address_string() const;
+ std::string gateway_address_string(Address::Family family) const;
const std::string &peer_name() const { return peer_name_; }
const std::string &peer_basename() const { return peer_basename_; }
std::string router_type() const { return router_type_; }
@@ -344,7 +347,6 @@ class BgpPeer : public IPeer {
std::string BytesToHexString(const u_int8_t *msg, size_t size);
BgpServer *server_;
- // Backpointer to routing instance
RoutingInstance *rtinstance_;
TcpSession::Endpoint endpoint_;
BgpPeerKey peer_key_;
diff --git a/src/bgp/bgp_peer.sandesh b/src/bgp/bgp_peer.sandesh
index e656add3c63..fbb6dd1c0c0 100644
--- a/src/bgp/bgp_peer.sandesh
+++ b/src/bgp/bgp_peer.sandesh
@@ -39,6 +39,7 @@ struct ShowBgpNeighborFamily {
1: string family;
2: u32 loop_count;
3: u32 prefix_limit;
+ 4: string gateway_address;
}
struct PeerCloseInfo {
@@ -539,6 +540,7 @@ struct ShowBgpNeighborFamilyConfig {
1: string family;
2: i32 loop_count;
3: i32 prefix_limit;
+ 4: string gateway_address;
}
struct ShowBgpNeighborConfig {
diff --git a/src/bgp/bgp_show_config.cc b/src/bgp/bgp_show_config.cc
index 81f75510ba1..085f4786698 100644
--- a/src/bgp/bgp_show_config.cc
+++ b/src/bgp/bgp_show_config.cc
@@ -350,6 +350,15 @@ static void FillBgpNeighborConfigInfo(ShowBgpNeighborConfig *sbnc,
sbnfc.family = family_config.family;
sbnfc.loop_count = family_config.loop_count;
sbnfc.prefix_limit = family_config.prefix_limit;
+ if (family_config.family == "inet") {
+ IpAddress address = neighbor->gateway_address(Address::INET);
+ if (!address.is_unspecified())
+ sbnfc.gateway_address = address.to_string();
+ } else if (family_config.family == "inet6") {
+ IpAddress address = neighbor->gateway_address(Address::INET6);
+ if (!address.is_unspecified())
+ sbnfc.gateway_address = address.to_string();
+ }
sbnfc_list.push_back(sbnfc);
}
sbnc->set_family_attributes_list(sbnfc_list);
diff --git a/src/bgp/test/bgp_config_test.cc b/src/bgp/test/bgp_config_test.cc
index db361b6c590..1b6da2832bb 100644
--- a/src/bgp/test/bgp_config_test.cc
+++ b/src/bgp/test/bgp_config_test.cc
@@ -654,6 +654,64 @@ TEST_F(BgpConfigTest, BGPaaSNeighbors6) {
task_util::WaitForIdle();
}
+TEST_F(BgpConfigTest, BGPaaSNeighbors7) {
+ string content;
+ content = FileRead("controller/src/bgp/testdata/config_test_40a.xml");
+ EXPECT_TRUE(parser_.Parse(content));
+ task_util::WaitForIdle();
+
+ RoutingInstance *rti =
+ server_.routing_instance_mgr()->GetRoutingInstance("test");
+ TASK_UTIL_ASSERT_TRUE(rti != NULL);
+ TASK_UTIL_EXPECT_EQ(2, rti->peer_manager()->size());
+
+ TASK_UTIL_EXPECT_TRUE(
+ rti->peer_manager()->PeerLookup("test:vm1:0") != NULL);
+ BgpPeer *peer1 = rti->peer_manager()->PeerLookup("test:vm1:0");
+ TASK_UTIL_EXPECT_TRUE(GetPeerResolvePaths(peer1));
+ TASK_UTIL_EXPECT_EQ("10.0.0.254",
+ peer1->gateway_address_string(Address::INET));
+ TASK_UTIL_EXPECT_EQ("::ffff:10.0.0.254",
+ peer1->gateway_address_string(Address::INET6));
+
+ TASK_UTIL_EXPECT_TRUE(
+ rti->peer_manager()->PeerLookup("test:vm2:0") != NULL);
+ BgpPeer *peer2 = rti->peer_manager()->PeerLookup("test:vm2:0");
+ TASK_UTIL_EXPECT_TRUE(GetPeerResolvePaths(peer2));
+ TASK_UTIL_EXPECT_EQ("10.0.0.254",
+ peer2->gateway_address_string(Address::INET));
+ TASK_UTIL_EXPECT_EQ("::ffff:10.0.0.254",
+ peer2->gateway_address_string(Address::INET6));
+
+ // Update gateway addresses.
+ content = FileRead("controller/src/bgp/testdata/config_test_40b.xml");
+ EXPECT_TRUE(parser_.Parse(content));
+ task_util::WaitForIdle();
+
+ // Verify that the v4 and v6 gateway addresses are updated for test:vm1.
+ TASK_UTIL_EXPECT_EQ(peer1, server_.FindPeer(peer1->endpoint()));
+ TASK_UTIL_EXPECT_TRUE(GetPeerResolvePaths(peer1));
+ TASK_UTIL_EXPECT_EQ("10.0.0.253",
+ peer1->gateway_address_string(Address::INET));
+ TASK_UTIL_EXPECT_EQ("::ffff:10.0.0.253",
+ peer1->gateway_address_string(Address::INET6));
+
+ // Verify that the v4 and v6 gateway addresses are updated for test:vm2.
+ TASK_UTIL_EXPECT_EQ(peer2, server_.FindPeer(peer2->endpoint()));
+ TASK_UTIL_EXPECT_TRUE(GetPeerResolvePaths(peer2));
+ TASK_UTIL_EXPECT_EQ("10.0.0.253",
+ peer2->gateway_address_string(Address::INET));
+ TASK_UTIL_EXPECT_EQ("::ffff:10.0.0.253",
+ peer2->gateway_address_string(Address::INET6));
+
+ // Cleanup.
+ boost::replace_all(content, "", "");
+ boost::replace_all(content, "", "");
+ EXPECT_TRUE(parser_.Parse(content));
+ task_util::WaitForIdle();
+ TASK_UTIL_EXPECT_EQ(0, rti->peer_manager()->size());
+}
+
TEST_F(BgpConfigTest, MasterNeighborAttributes) {
string content_a = FileRead("controller/src/bgp/testdata/config_test_35a.xml");
EXPECT_TRUE(parser_.Parse(content_a));
diff --git a/src/bgp/testdata/config_test_40a.xml b/src/bgp/testdata/config_test_40a.xml
new file mode 100644
index 00000000000..7b89ff8c0a6
--- /dev/null
+++ b/src/bgp/testdata/config_test_40a.xml
@@ -0,0 +1,75 @@
+
+
+
+ 192.168.1.1
+ 64512
+ 192.168.1.1
+
+
+ target:64512:1
+
+ bgpaas-server
+ 64512
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+ bgpaas-client
+ 65001
+ 10.0.0.1
+ 10.0.0.254
+ ::ffff:10.0.0.254
+ 1024
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+ bgpaas-client
+ 65002
+ 10.0.0.2
+ 10.0.0.254
+ ::ffff:10.0.0.254
+ 1025
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+
diff --git a/src/bgp/testdata/config_test_40b.xml b/src/bgp/testdata/config_test_40b.xml
new file mode 100644
index 00000000000..b77508a7df5
--- /dev/null
+++ b/src/bgp/testdata/config_test_40b.xml
@@ -0,0 +1,75 @@
+
+
+
+ 192.168.1.1
+ 64512
+ 192.168.1.1
+
+
+ target:64512:1
+
+ bgpaas-server
+ 64512
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+ bgpaas-client
+ 65001
+ 10.0.0.1
+ 10.0.0.253
+ ::ffff:10.0.0.253
+ 1024
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+ bgpaas-client
+ 65002
+ 10.0.0.2
+ 10.0.0.253
+ ::ffff:10.0.0.253
+ 1025
+
+
+ inet
+
+
+ inet6
+
+
+ inet-vpn
+
+
+
+
+
diff --git a/src/schema/bgp_schema.xsd b/src/schema/bgp_schema.xsd
index 0dea2958278..f039758f0d1 100644
--- a/src/schema/bgp_schema.xsd
+++ b/src/schema/bgp_schema.xsd
@@ -106,6 +106,17 @@
+
+
+ The gateway-address and ipv6-gateway-addreess fields are used only
+ for router-type bgpaas-client. They hold the ipv4 and ipv6 gateway
+ address for the ipv4 and ipv6 subnets from which the client has IP
+ addresses. The values are used as nexthops when advertising routes
+ to the client via bgp.
+ Note that the ipv6-gateway-address can be a regular ipv6 address or
+ a ipv4-mapped-ipv6 adddress.
+
+
@@ -118,6 +129,8 @@
+
+
diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd
index 07e1b15a9e2..81b8cb37e07 100644
--- a/src/schema/vnc_cfg.xsd
+++ b/src/schema/vnc_cfg.xsd
@@ -1414,6 +1414,16 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0">
+
+
+
+ This is used to indicate if the client bgp implementation expects
+ to receive a ipv4-mapped ipv6 address (as opposed to regular ipv6
+ address) as the bgp nexthop for ipv6 routes.
+
+
+