Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 : #include <iostream>
5 :
6 : #include <base/logging.h>
7 : #include <cmn/agent_cmn.h>
8 : #include <init/agent_param.h>
9 : #include <cfg/cfg_init.h>
10 :
11 : #include <oper/vm.h>
12 : #include <oper/vn.h>
13 : #include <oper/vrf.h>
14 : #include <oper/nexthop.h>
15 : #include <oper/mpls.h>
16 : #include <oper/mirror_table.h>
17 : #include <oper/route_common.h>
18 : #include <oper/interface_common.h>
19 : #include <oper/vrf_assign.h>
20 :
21 : #include <vgw/cfg_vgw.h>
22 : #include <vgw/vgw.h>
23 :
24 : using namespace std;
25 :
26 0 : VirtualGateway::VirtualGateway(Agent *agent) : agent_(agent) {
27 0 : vgw_config_table_ = agent->params()->vgw_config_table();
28 0 : }
29 :
30 : struct VirtualGatewayState : DBState {
31 0 : VirtualGatewayState() : active_(false) { }
32 0 : ~VirtualGatewayState() { }
33 : bool active_;
34 : };
35 :
36 0 : void VirtualGateway::InterfaceNotify(DBTablePartBase *partition, DBEntryBase *entry) {
37 0 : if ((static_cast<Interface *>(entry))->type() != Interface::INET)
38 0 : return;
39 :
40 0 : InetInterface *intf = static_cast<InetInterface *>(entry);
41 0 : if (intf->sub_type() != InetInterface::SIMPLE_GATEWAY)
42 0 : return;
43 :
44 : VirtualGatewayState *state = static_cast<VirtualGatewayState *>
45 0 : (entry->GetState(partition->parent(), listener_id_));
46 :
47 0 : if (entry->IsDeleted()) {
48 0 : if (state) {
49 0 : entry->ClearState(partition->parent(), listener_id_);
50 0 : delete state;
51 : }
52 0 : return;
53 : }
54 :
55 0 : bool active = intf->ipv4_active();
56 0 : VirtualGatewayConfig cfg(intf->name());
57 : VirtualGatewayConfigTable::Table::iterator it =
58 0 : vgw_config_table_->table().find(cfg);
59 0 : if (it == vgw_config_table_->table().end())
60 0 : return;
61 :
62 0 : if (state == NULL) {
63 0 : state = new VirtualGatewayState();
64 0 : entry->SetState(partition->parent(), listener_id_, state);
65 0 : it->set_interface(intf);
66 : }
67 :
68 : InetUnicastAgentRouteTable *rt_table =
69 0 : (agent_->vrf_table()->GetInet4UnicastRouteTable(it->vrf_name()));
70 :
71 0 : state->active_ = active;
72 :
73 : // Add gateway routes in virtual-network.
74 : // BGP will export the route to other compute nodes
75 0 : VirtualGatewayConfig::SubnetList empty_list;
76 0 : if (active) {
77 0 : RouteUpdate(*it, it->routes().size(), rt_table,
78 : it->routes(), empty_list, true, false);
79 : } else {
80 0 : RouteUpdate(*it, it->routes().size(), rt_table,
81 : empty_list, it->routes(), false, true);
82 : }
83 :
84 0 : if (active) {
85 : // Packets received on fabric vrf and destined to IP address in
86 : // "public" network must reach kernel. Add a route in "fabric" VRF
87 : // inside vrouter to trap packets destined to "public" network
88 0 : SubnetUpdate(it->vrf_name(), rt_table, it->subnets(), empty_list);
89 : } else {
90 : // Delete the trap route added above
91 0 : SubnetUpdate(it->vrf_name(), rt_table, empty_list, it->subnets());
92 : }
93 0 : }
94 :
95 0 : void VirtualGateway::RegisterDBClients() {
96 0 : listener_id_ = agent_->interface_table()->Register
97 0 : (boost::bind(&VirtualGateway::InterfaceNotify, this, _1, _2));
98 0 : }
99 :
100 : // Create VRF for "public" virtual-network
101 0 : void VirtualGateway::CreateVrf() {
102 0 : if (vgw_config_table_ == NULL) {
103 0 : return;
104 : }
105 0 : VirtualGatewayConfigTable::Table::iterator it;
106 0 : const VirtualGatewayConfigTable::Table &table = vgw_config_table_->table();
107 0 : for (it = table.begin(); it != table.end(); it++) {
108 0 : CreateVrf(it->vrf_name());
109 : }
110 : }
111 :
112 0 : void VirtualGateway::CreateVrf(const std::string &vrf_name) {
113 0 : agent_->vrf_table()->CreateVrf(
114 0 : vrf_name, boost::uuids::nil_uuid(), VrfData::GwVrf);
115 0 : }
116 :
117 0 : void VirtualGateway::DeleteVrf(const std::string &vrf_name) {
118 0 : agent_->vrf_table()->DeleteVrf(vrf_name, VrfData::GwVrf);
119 0 : }
120 :
121 : // Create virtual-gateway interface
122 0 : void VirtualGateway::CreateInterfaces(Interface::Transport transport) {
123 0 : if (vgw_config_table_ == NULL) {
124 0 : return;
125 : }
126 :
127 0 : VirtualGatewayConfigTable::Table::iterator it;
128 0 : const VirtualGatewayConfigTable::Table &table = vgw_config_table_->table();
129 0 : for (it = table.begin(); it != table.end(); it++) {
130 0 : CreateInterface(it->interface_name(), it->vrf_name(), transport);
131 : }
132 : }
133 :
134 0 : void VirtualGateway::CreateInterface(const std::string &interface_name,
135 : const std::string &vrf_name,
136 : Interface::Transport transport) {
137 0 : InetInterface::Create(agent_->interface_table(), interface_name,
138 : InetInterface::SIMPLE_GATEWAY, vrf_name,
139 0 : Ip4Address(0), 0, Ip4Address(0), Agent::NullString(),
140 : "", transport);
141 0 : }
142 :
143 0 : void VirtualGateway::DeleteInterface(const std::string &interface_name) {
144 0 : InetInterface::Delete(agent_->interface_table(), interface_name);
145 0 : }
146 :
147 : void
148 0 : VirtualGateway::SubnetUpdate(const VirtualGatewayConfig &vgw,
149 : const VirtualGatewayConfig::SubnetList &add_list,
150 : const VirtualGatewayConfig::SubnetList &del_list) {
151 0 : if (vgw.get_interface() && !vgw.get_interface()->ipv4_active())
152 0 : return;
153 :
154 : InetUnicastAgentRouteTable *rt_table =
155 0 : (agent_->vrf_table()->GetInet4UnicastRouteTable(vgw.vrf_name()));
156 0 : if (!rt_table)
157 0 : return;
158 :
159 0 : SubnetUpdate(vgw.vrf_name(), rt_table, add_list, del_list);
160 : }
161 :
162 : void
163 0 : VirtualGateway::SubnetUpdate(const std::string &vrf,
164 : InetUnicastAgentRouteTable *rt_table,
165 : const VirtualGatewayConfig::SubnetList &add_list,
166 : const VirtualGatewayConfig::SubnetList &del_list) {
167 0 : for (uint32_t idx = 0; idx < add_list.size(); idx++) {
168 0 : Ip4Address addr = Address::GetIp4SubnetAddress(add_list[idx].ip_,
169 0 : add_list[idx].plen_);
170 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE,
171 0 : boost::uuids::nil_uuid(),
172 0 : agent_->vhost_interface_name());
173 0 : rt_table->AddVHostRecvRouteReq(agent_->vgw_peer(),
174 0 : agent_->fabric_vrf_name(),
175 : vmi_key,
176 0 : addr, add_list[idx].plen_,
177 : vrf, false, true);
178 0 : }
179 0 : for (uint32_t idx = 0; idx < del_list.size(); idx++) {
180 0 : Ip4Address addr = Address::GetIp4SubnetAddress(del_list[idx].ip_,
181 0 : del_list[idx].plen_);
182 0 : rt_table->DeleteReq(agent_->vgw_peer(), agent_->fabric_vrf_name(),
183 0 : addr, del_list[idx].plen_, NULL);
184 : }
185 0 : }
186 :
187 : void
188 0 : VirtualGateway::RouteUpdate(const VirtualGatewayConfig &vgw,
189 : const VirtualGatewayConfig::SubnetList &new_list,
190 : const VirtualGatewayConfig::SubnetList &add_list,
191 : const VirtualGatewayConfig::SubnetList &del_list,
192 : bool add_default_route) {
193 0 : if (vgw.get_interface() && !vgw.get_interface()->ipv4_active())
194 0 : return;
195 :
196 : InetUnicastAgentRouteTable *rt_table =
197 0 : (agent_->vrf_table()->GetInet4UnicastRouteTable(vgw.vrf_name()));
198 :
199 0 : RouteUpdate(vgw, new_list.size(), rt_table, add_list, del_list,
200 : add_default_route, true);
201 : }
202 :
203 : void
204 0 : VirtualGateway::RouteUpdate(const VirtualGatewayConfig &vgw,
205 : uint32_t new_list_size,
206 : InetUnicastAgentRouteTable *rt_table,
207 : const VirtualGatewayConfig::SubnetList &add_list,
208 : const VirtualGatewayConfig::SubnetList &del_list,
209 : bool add_default_route, bool del_default_route) {
210 0 : VnListType name_list;
211 0 : name_list.insert(vgw.vrf_name());
212 0 : if (vgw.routes().size() == 0 && del_default_route) {
213 : // no routes earlier, remove default route
214 0 : rt_table->DeleteReq(agent_->vgw_peer(), vgw.vrf_name(),
215 0 : Ip4Address(0), 0, NULL);
216 0 : } else if (new_list_size == 0 && add_default_route) {
217 : // no routes now, add a default route
218 0 : rt_table->AddInetInterfaceRouteReq(agent_->vgw_peer(), vgw.vrf_name(),
219 0 : Ip4Address(0), 0,
220 : vgw.interface_name(),
221 0 : vgw.get_interface()->label(),
222 : name_list);
223 : }
224 : // remove old routes, add new routes
225 0 : for (uint32_t idx = 0; idx < del_list.size(); idx++) {
226 0 : Ip4Address addr = Address::GetIp4SubnetAddress(del_list[idx].ip_,
227 0 : del_list[idx].plen_);
228 0 : rt_table->DeleteReq(agent_->vgw_peer(), vgw.vrf_name(),
229 0 : addr, del_list[idx].plen_, NULL);
230 : }
231 0 : for (uint32_t idx = 0; idx < add_list.size(); idx++) {
232 0 : Ip4Address addr = Address::GetIp4SubnetAddress(add_list[idx].ip_,
233 0 : add_list[idx].plen_);
234 0 : rt_table->AddInetInterfaceRouteReq(agent_->vgw_peer(),
235 : vgw.vrf_name(), addr,
236 0 : add_list[idx].plen_,
237 : vgw.interface_name(),
238 0 : vgw.get_interface()->label(),
239 : name_list);
240 : }
241 0 : }
242 :
243 0 : void VirtualGateway::Init() {
244 0 : }
245 :
246 0 : void VirtualGateway::Shutdown() {
247 0 : if (vgw_config_table_ == NULL)
248 0 : return;
249 :
250 0 : VirtualGatewayConfigTable::Table::iterator it;
251 0 : const VirtualGatewayConfigTable::Table &table = vgw_config_table_->table();
252 0 : for (it = table.begin(); it != table.end(); it++) {
253 : // Delete Interface
254 0 : InetInterface::Delete(agent_->interface_table(),
255 : it->interface_name());
256 :
257 : // Delete VRF for "public" virtual-network
258 0 : agent_->vrf_table()->DeleteStaticVrf(it->vrf_name());
259 : }
260 : }
|