OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cfg_vgw.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 #include <iostream>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 
9 #include <sys/stat.h>
10 
11 #include <boost/property_tree/ini_parser.hpp>
12 #include <boost/algorithm/string.hpp>
13 #include <boost/foreach.hpp>
14 #include <vector>
15 #include <pugixml/pugixml.hpp>
16 #include <base/logging.h>
17 
18 #include <cmn/agent_cmn.h>
19 #include <init/agent_param.h>
20 #include <cfg/cfg_init.h>
21 #include <vgw/cfg_vgw.h>
22 #include <oper/interface_common.h>
23 #include <vgw/vgw.h>
24 
25 using namespace std;
26 using namespace boost::property_tree;
27 using namespace boost::uuids;
28 using boost::optional;
29 
30 // Config init. Read the "gateway" node and add the configuration
31 // Handle only one gateway config for now
33 (const boost::property_tree::ptree pt) {
34  const std::string gw_str = "GATEWAY";
35 
36  BOOST_FOREACH(const ptree::value_type &section, pt) {
37  if (section.first.compare(0, gw_str.size(), gw_str) != 0) {
38  continue;
39  }
40  string vrf = "";
41  string interfacestr = "";
44  BOOST_FOREACH(const ptree::value_type &key, section.second) {
45  if (key.first.compare("routing_instance") == 0) {
46  vrf = key.second.get_value<string>();
47  }
48  if (key.first.compare("interface") == 0) {
49  interfacestr = key.second.get_value<string>();
50  }
51  if (key.first.compare("ip_blocks") == 0) {
52  BuildSubnetList(key.second.get_value<string>(), subnets);
53  }
54  if (key.first.compare("routes") == 0) {
55  BuildSubnetList(key.second.get_value<string>(), routes);
56  }
57  }
58  if (vrf == "" || interfacestr == "" || subnets.size() == 0) {
59  LOG(ERROR, "Error in config file. Invalid/incomplete gateway "
60  "section" << section.first);
61  continue;
62  }
63 
64  std::sort(subnets.begin(), subnets.end());
65  std::sort(routes.begin(), routes.end());
66  table_.insert(VirtualGatewayConfig(interfacestr, vrf,
67  subnets, routes, (uint32_t) -1));
68  }
69  return;
70 }
71 
73  (const string &subnets, VirtualGatewayConfig::SubnetList &results) {
74  Ip4Address addr;
75  int plen;
76  boost::system::error_code ec;
77  results.clear();
78  if (!subnets.empty()) {
79  vector<string> tokens;
80  boost::split(tokens, subnets, boost::is_any_of(" "));
81  vector<string>::iterator it = tokens.begin();
82  while (it != tokens.end()) {
83  std::string str = *it;
84  boost::algorithm::trim(str);
85  ++it;
86  ec = Ip4PrefixParse(str, &addr, &plen);
87  if (ec.failed() || plen >= 32) {
88  LOG(ERROR, "Error in config file. Invalid gateway "
89  "ip_block/route " << str);
90  continue;
91  }
92  results.push_back(VirtualGatewayConfig::Subnet(addr, plen));
93  }
94  }
95 }
96 
98  agent_ = agent;
99  work_queue_.reset(new WorkQueue<boost::shared_ptr<VirtualGatewayData> >
100  (agent_->task_scheduler()->GetTaskId("db::DBTable"), 0,
102  this, _1)));
103  work_queue_->set_name("VGW");
104 }
105 
107  work_queue_->Shutdown();
108 }
109 
111  boost::shared_ptr<VirtualGatewayData> request) {
112  work_queue_->Enqueue(request);
113 }
114 
116  boost::shared_ptr<VirtualGatewayData> request) {
117  switch(request->message_type_) {
119  BOOST_FOREACH(VirtualGatewayInfo &vgw, request->vgw_list_) {
120  AddVgw(vgw, request->version_);
121  }
122  break;
123 
125  BOOST_FOREACH(VirtualGatewayInfo &vgw, request->vgw_list_) {
126  DeleteVgw(vgw.interface_name_);
127  }
128  break;
129 
131  DeleteAllOldVersionVgw(request->version_);
132  break;
133 
134  default:
135  assert(0);
136  }
137  return true;
138 }
139 
140 // Add / modify a virtual gateway
142  std::sort(vgw.subnets_.begin(), vgw.subnets_.end());
143  std::sort(vgw.routes_.begin(), vgw.routes_.end());
144  Table::iterator it = table_.find(vgw.interface_name_);
146  if (agent_->vrouter_on_nic_mode() ||
147  agent_->vrouter_on_host_dpdk()) {
148  transport = Interface::TRANSPORT_PMD;
149  }
150  if (it == table_.end()) {
151  // Add new gateway
152  table_.insert(VirtualGatewayConfig(vgw.interface_name_, vgw.vrf_name_,
153  vgw.subnets_, vgw.routes_, version));
154  agent_->vgw()->CreateVrf(vgw.vrf_name_);
155  agent_->vgw()->CreateInterface(vgw.interface_name_, vgw.vrf_name_,
156  transport);
157  } else {
158  // modify existing gateway
159  if (vgw.vrf_name_ != it->vrf_name()) {
160  LOG(DEBUG, "Virtual Gateway : change of vrf is not allowed; " <<
161  "Interface : " << vgw.interface_name_ << " Old VRF : " <<
162  it->vrf_name() << " New VRF : " << vgw.vrf_name_);
163  return false;
164  }
165  VirtualGatewayConfig::SubnetList add_list, del_list;
166  if (FindChange(it->subnets(), vgw.subnets_, add_list, del_list)) {
167  agent_->vgw()->SubnetUpdate(*it, add_list, del_list);
168  it->set_subnets(vgw.subnets_);
169  }
170 
171  add_list.clear();
172  del_list.clear();
173  if (FindChange(it->routes(), vgw.routes_, add_list, del_list)) {
174  agent_->vgw()->RouteUpdate(*it, vgw.routes_, add_list, del_list, true);
175  it->set_routes(vgw.routes_);
176  }
177  it->set_version(version);
178  }
179  return true;
180 }
181 
182 // Delete a virtual gateway
183 bool VirtualGatewayConfigTable::DeleteVgw(const std::string &interface_name) {
184  Table::iterator it = table_.find(interface_name);
185  if (it != table_.end()) {
186  DeleteVgw(it);
187  return true;
188  }
189 
190  LOG(DEBUG, "Virtual Gateway delete : interface not present; " <<
191  "Interface : " << interface_name);
192  return false;
193 }
194 
195 void VirtualGatewayConfigTable::DeleteVgw(Table::iterator it) {
197  agent_->vgw()->SubnetUpdate(*it, empty_list, it->subnets());
198  agent_->vgw()->RouteUpdate(*it, empty_list, empty_list,
199  it->routes(), false);
200  agent_->vgw()->DeleteInterface(it->interface_name());
201  agent_->vgw()->DeleteVrf(it->vrf_name());
202  table_.erase(it);
203 }
204 
205 // delete all entries from previous version
207  for (Table::iterator it = table_.begin(); it != table_.end();) {
208  if (it->version() < version) {
209  DeleteVgw(it++);
210  } else {
211  it++;
212  }
213  }
214 }
215 
217  const VirtualGatewayConfig::SubnetList &old_subnets,
218  const VirtualGatewayConfig::SubnetList &new_subnets,
221  bool change = false;
222  VirtualGatewayConfig::SubnetList::const_iterator it_old = old_subnets.begin();
223  VirtualGatewayConfig::SubnetList::const_iterator it_new = new_subnets.begin();
224  while (it_old != old_subnets.end() && it_new != new_subnets.end()) {
225  if (*it_old < *it_new) {
226  // old entry is deleted
227  del_list.push_back(*it_old);
228  change = true;
229  it_old++;
230  } else if (*it_new < *it_old) {
231  // new entry
232  add_list.push_back(*it_new);
233  change = true;
234  it_new++;
235  } else {
236  // no change in entry
237  it_old++;
238  it_new++;
239  }
240  }
241 
242  // delete remaining old entries
243  for (; it_old != old_subnets.end(); ++it_old) {
244  del_list.push_back(*it_old);
245  change = true;
246  }
247 
248  // add remaining new entries
249  for (; it_new != new_subnets.end(); ++it_new) {
250  add_list.push_back(*it_new);
251  change = true;
252  }
253 
254  return change;
255 }
bool DeleteVgw(const std::string &interface_name)
Definition: cfg_vgw.cc:183
void Enqueue(boost::shared_ptr< VirtualGatewayData > request)
Definition: cfg_vgw.cc:110
boost::system::error_code Ip4PrefixParse(const string &str, Ip4Address *addr, int *plen)
Definition: address.cc:107
void DeleteAllOldVersionVgw(uint32_t version)
Definition: cfg_vgw.cc:206
VirtualGatewayConfig::SubnetList routes_
Definition: cfg_vgw.h:79
void InitFromConfig(const boost::property_tree::ptree pt)
Definition: cfg_vgw.cc:33
std::string vrf_name_
Definition: cfg_vgw.h:77
Definition: agent.h:358
bool FindChange(const VirtualGatewayConfig::SubnetList &old_subnets, const VirtualGatewayConfig::SubnetList &new_subnets, VirtualGatewayConfig::SubnetList &add_list, VirtualGatewayConfig::SubnetList &del_list)
Definition: cfg_vgw.cc:216
bool ProcessRequest(boost::shared_ptr< VirtualGatewayData > request)
Definition: cfg_vgw.cc:115
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
bool AddVgw(VirtualGatewayInfo &vgw, uint32_t version)
Definition: cfg_vgw.cc:141
#define LOG(_Level, _Msg)
Definition: logging.h:33
std::vector< Subnet > SubnetList
Definition: cfg_vgw.h:30
void BuildSubnetList(const std::string &subnets, VirtualGatewayConfig::SubnetList &results)
Definition: cfg_vgw.cc:73
VirtualGatewayConfig::SubnetList subnets_
Definition: cfg_vgw.h:78
void InitDone(Agent *agent)
Definition: cfg_vgw.cc:97
std::string interface_name_
Definition: cfg_vgw.h:76