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