From 4ada41f32e5bf0de274e07ddd6e773eca55a836f Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Fri, 4 Mar 2016 15:08:31 -0800 Subject: [PATCH] BGPaaSv2: Parse and process gateway address for bgp peer Change-Id: Id4e7e2b26ac1650f0426680af233f924ca630668 Partial-Bug: 1552952 --- src/bgp/bgp_config.cc | 24 +++++++++ src/bgp/bgp_config.h | 5 ++ src/bgp/bgp_config_ifmap.cc | 23 ++++++++- src/bgp/bgp_peer.cc | 15 ++++++ src/bgp/bgp_peer.h | 4 +- src/bgp/bgp_peer.sandesh | 2 + src/bgp/bgp_show_config.cc | 9 ++++ src/bgp/test/bgp_config_test.cc | 58 +++++++++++++++++++++ src/bgp/testdata/config_test_40a.xml | 75 ++++++++++++++++++++++++++++ src/bgp/testdata/config_test_40b.xml | 75 ++++++++++++++++++++++++++++ src/schema/bgp_schema.xsd | 13 +++++ src/schema/vnc_cfg.xsd | 10 ++++ 12 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 src/bgp/testdata/config_test_40a.xml create mode 100644 src/bgp/testdata/config_test_40b.xml 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. + + +