Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <boost/uuid/uuid_io.hpp>
7 :
8 : #include <cmn/agent_cmn.h>
9 : #include <route/route.h>
10 :
11 : #include <oper/route_common.h>
12 : #include <oper/vrf.h>
13 : #include <oper/tunnel_nh.h>
14 : #include <oper/mpls.h>
15 : #include <oper/vxlan.h>
16 : #include <oper/mirror_table.h>
17 : #include <oper/multicast.h>
18 : #include <controller/controller_export.h>
19 : #include <controller/controller_peer.h>
20 : #include <controller/controller_init.h>
21 : #include <oper/agent_sandesh.h>
22 :
23 : using namespace std;
24 : using namespace boost::asio;
25 :
26 0 : static void MulticastTableEnqueue(Agent *agent, DBRequest *req) {
27 0 : AgentRouteTable *table = agent->fabric_inet4_multicast_table();
28 0 : if (table) {
29 0 : table->Enqueue(req);
30 : }
31 0 : }
32 :
33 0 : static void MulticastTableProcess(Agent *agent, const string &vrf_name,
34 : DBRequest &req) {
35 : AgentRouteTable *table =
36 0 : agent->vrf_table()->GetInet4MulticastRouteTable(vrf_name);
37 0 : if (table) {
38 0 : table->Process(req);
39 : }
40 0 : }
41 :
42 74 : DBTableBase *Inet4MulticastAgentRouteTable::CreateTable(DB *db,
43 : const std::string &name) {
44 74 : AgentRouteTable *table = new Inet4MulticastAgentRouteTable(db, name);
45 74 : table->Init();
46 : //table->InitRouteTable(db, table, name, Agent::INET4_MULTICAST);
47 74 : return table;
48 : }
49 :
50 : void
51 0 : Inet4MulticastAgentRouteTable::AddMulticastRoute(const string &vrf_name,
52 : const string &vn_name,
53 : const Ip4Address &src_addr,
54 : const Ip4Address &grp_addr,
55 : ComponentNHKeyList
56 : &component_nh_key_list) {
57 0 : DBRequest nh_req;
58 : NextHopKey *nh_key;
59 : CompositeNHData *nh_data;
60 :
61 0 : nh_key = new CompositeNHKey(Composite::L3COMP, true, component_nh_key_list,
62 0 : vrf_name);
63 0 : nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
64 0 : nh_req.key.reset(nh_key);
65 0 : nh_data = new CompositeNHData();
66 0 : nh_req.data.reset(nh_data);
67 :
68 0 : DBRequest req;
69 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
70 : Inet4MulticastRouteKey *rt_key = new Inet4MulticastRouteKey(vrf_name,
71 : grp_addr,
72 0 : src_addr);
73 : MulticastRoute *data = new MulticastRoute(vn_name,
74 : MplsTable::kInvalidLabel,
75 : VxLanTable::kInvalidvxlan_id,
76 0 : TunnelType::AllType(),
77 0 : nh_req, Composite::L3COMP, 0);
78 0 : req.key.reset(rt_key);
79 0 : req.data.reset(data);
80 0 : MulticastTableEnqueue(Agent::GetInstance(), &req);
81 0 : }
82 :
83 : void
84 0 : Inet4MulticastAgentRouteTable::AddMulticastRoute(const Peer *peer,
85 : const string &vrf_name,
86 : const Ip4Address &src_addr,
87 : const Ip4Address &grp_addr,
88 : uint32_t ethernet_tag,
89 : AgentRouteData *data) {
90 :
91 0 : DBRequest req;
92 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
93 : Inet4MulticastRouteKey *rt_key = new Inet4MulticastRouteKey(peer, vrf_name,
94 0 : grp_addr, src_addr, ethernet_tag);
95 0 : req.key.reset(rt_key);
96 0 : req.data.reset(data);
97 0 : MulticastTableEnqueue(Agent::GetInstance(), &req);
98 0 : }
99 :
100 : void
101 0 : Inet4MulticastAgentRouteTable::AddVHostRecvRoute(const string &vm_vrf,
102 : const string &interface_name,
103 : const Ip4Address &addr,
104 : bool policy)
105 : {
106 0 : DBRequest req;
107 :
108 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
109 0 : Inet4MulticastRouteKey *rt_key = new Inet4MulticastRouteKey(vm_vrf, addr);
110 0 : req.key.reset(rt_key);
111 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE,
112 0 : boost::uuids::nil_uuid(), interface_name);
113 : ReceiveRoute *data =
114 : new ReceiveRoute(intf_key, MplsTable::kInvalidLabel,
115 0 : TunnelType::AllType(), policy,
116 0 : Agent::GetInstance()->fabric_vn_name());
117 : //data->SetMulticast(true);
118 0 : req.data.reset(data);
119 0 : MulticastTableEnqueue(Agent::GetInstance(), &req);
120 0 : }
121 :
122 : void
123 0 : Inet4MulticastAgentRouteTable::DeleteMulticastRoute(const string &vrf_name,
124 : const Ip4Address &src_addr,
125 : const Ip4Address &grp_addr)
126 : {
127 0 : DBRequest req;
128 :
129 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
130 : Inet4MulticastRouteKey *rt_key = new Inet4MulticastRouteKey(vrf_name,
131 : grp_addr,
132 0 : src_addr);
133 :
134 0 : req.key.reset(rt_key);
135 0 : req.data.reset(NULL);
136 0 : MulticastTableEnqueue(Agent::GetInstance(), &req);
137 0 : }
138 :
139 : void
140 0 : Inet4MulticastAgentRouteTable::DeleteMulticastRoute(const Peer *peer,
141 : const string &vrf_name,
142 : const Ip4Address &src_addr,
143 : const Ip4Address &grp_addr,
144 : uint32_t ethernet_tag,
145 : COMPOSITETYPE type) {
146 :
147 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
148 : Inet4MulticastRouteKey *rt_key = new Inet4MulticastRouteKey(peer, vrf_name,
149 0 : grp_addr, src_addr, ethernet_tag);
150 0 : req.key.reset(rt_key);
151 :
152 0 : DBRequest nh_req;
153 0 : const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
154 0 : if (bgp_peer) {
155 0 : req.data.reset(new MulticastRoute("", 0, ethernet_tag,
156 0 : TunnelType::AllType(), nh_req, type,
157 0 : bgp_peer->sequence_number()));
158 : } else {
159 0 : req.data.reset(new MulticastRoute("", 0, ethernet_tag,
160 0 : TunnelType::AllType(), nh_req, type, 0));
161 : }
162 :
163 0 : MulticastTableEnqueue(Agent::GetInstance(), &req);
164 0 : }
165 :
166 0 : void Inet4MulticastAgentRouteTable::Delete(const string &vrf_name,
167 : const Ip4Address &src_addr,
168 : const Ip4Address &grp_addr) {
169 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
170 0 : req.key.reset(new Inet4MulticastRouteKey(vrf_name, grp_addr, src_addr));
171 0 : req.data.reset(NULL);
172 0 : MulticastTableProcess(Agent::GetInstance(), vrf_name, req);
173 0 : }
174 :
175 : AgentRoute *
176 0 : Inet4MulticastRouteKey::AllocRouteEntry(VrfEntry *vrf, bool is_multicast) const
177 : {
178 0 : Inet4MulticastRouteEntry * entry = new Inet4MulticastRouteEntry(vrf, dip_,
179 0 : sip_);
180 0 : return static_cast<AgentRoute *>(entry);
181 : }
182 :
183 0 : AgentRouteKey *Inet4MulticastRouteKey::Clone() const {
184 0 : return (new Inet4MulticastRouteKey(vrf_name_, dip_, sip_));
185 : }
186 :
187 : Inet4MulticastRouteEntry *
188 0 : Inet4MulticastAgentRouteTable::FindRoute(const Ip4Address &grp_addr,
189 : const Ip4Address &src_addr) {
190 :
191 0 : Inet4MulticastRouteEntry entry(vrf_entry(), grp_addr, src_addr);
192 0 : return static_cast<Inet4MulticastRouteEntry *>(FindActiveEntry(&entry));
193 0 : }
194 :
195 0 : string Inet4MulticastRouteKey::ToString() const {
196 0 : ostringstream str;
197 0 : str << "Group:";
198 0 : str << dip_.to_string();
199 0 : str << " Src:";
200 0 : str << sip_.to_string();
201 0 : return str.str();
202 0 : }
203 :
204 0 : string Inet4MulticastRouteEntry::ToString() const {
205 0 : ostringstream str;
206 0 : str << "Group:";
207 0 : str << dst_addr_.to_string();
208 0 : str << " Src:";
209 0 : str << src_addr_.to_string();
210 0 : return str.str();
211 0 : }
212 :
213 0 : int Inet4MulticastRouteEntry::CompareTo(const Route &rhs) const {
214 0 : const Inet4MulticastRouteEntry &a =
215 : static_cast<const Inet4MulticastRouteEntry &>(rhs);
216 :
217 0 : if (src_addr_ < a.src_addr_)
218 0 : return -1;
219 :
220 0 : if (src_addr_ > a.src_addr_)
221 0 : return 1;
222 :
223 0 : if (dst_addr_ < a.dst_addr_)
224 0 : return -1;
225 :
226 0 : if (dst_addr_ > a.dst_addr_)
227 0 : return 1;
228 :
229 0 : return 0;
230 : }
231 :
232 0 : DBEntryBase::KeyPtr Inet4MulticastRouteEntry::GetDBRequestKey() const {
233 : Inet4MulticastRouteKey *key =
234 0 : new Inet4MulticastRouteKey(vrf()->GetName(), dst_addr_,
235 0 : src_addr_);
236 0 : return DBEntryBase::KeyPtr(key);
237 : }
238 :
239 0 : void Inet4MulticastRouteEntry::SetKey(const DBRequestKey *key) {
240 0 : const Inet4MulticastRouteKey *k =
241 : static_cast<const Inet4MulticastRouteKey *>(key);
242 0 : SetVrf(Agent::GetInstance()->vrf_table()->FindVrfFromName(k->vrf_name()));
243 0 : Ip4Address grp(k->dest_ip_addr());
244 0 : Ip4Address src(k->src_ip_addr());
245 0 : set_dest_ip_addr(grp);
246 0 : set_src_ip_addr(src);
247 0 : }
248 :
249 0 : bool Inet4MulticastRouteEntry::ReComputePathAdd(AgentPath *path) {
250 0 : return ReComputeMulticastPaths(path, false);
251 : }
252 :
253 0 : bool Inet4MulticastRouteEntry::ReComputePathDeletion(AgentPath *path) {
254 0 : return ReComputeMulticastPaths(path, true);
255 : }
256 :
257 0 : bool Inet4MulticastRouteEntry::DBEntrySandesh(Sandesh *sresp, bool stale) const {
258 0 : Inet4McRouteResp *resp = static_cast<Inet4McRouteResp *>(sresp);
259 :
260 0 : RouteMcSandeshData data;
261 0 : data.set_src(src_ip_addr().to_string());
262 0 : data.set_grp(dest_ip_addr().to_string());
263 : MulticastGroupObject *mc_obj = MulticastHandler::GetInstance()->
264 0 : FindGroupObject(vrf()->GetName(), Ip4Address(), dest_ip_addr());
265 0 : Agent *agent = (static_cast<AgentRouteTable *>(get_table()))->agent();
266 0 : const NextHop *anh = GetActiveNextHop();
267 0 : if (!stale || anh || (mc_obj && (mc_obj->peer_identifier() != agent->controller()->
268 0 : multicast_sequence_number()))) {
269 0 : anh->SetNHSandeshData(data.nh);
270 : }
271 :
272 : std::vector<RouteMcSandeshData> &list =
273 0 : const_cast<std::vector<RouteMcSandeshData>&>(resp->get_route_list());
274 0 : list.push_back(data);
275 0 : return true;
276 0 : }
277 :
278 0 : bool Inet4MulticastRouteEntry::DBEntrySandesh(Sandesh *sresp,
279 : const Ip4Address &src_addr,
280 : const Ip4Address &dst_addr,
281 : bool stale) const {
282 :
283 0 : if (src_addr_ == src_addr && dst_addr_ == dst_addr) {
284 0 : return DBEntrySandesh(sresp, stale);
285 : }
286 :
287 0 : return false;
288 : }
289 :
290 0 : void Inet4McRouteReq::HandleRequest() const {
291 : VrfEntry *vrf =
292 0 : Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
293 0 : if (!vrf) {
294 0 : ErrorResp *resp = new ErrorResp();
295 0 : resp->set_context(context());
296 0 : resp->Response();
297 0 : return;
298 : }
299 :
300 0 : AgentSandeshPtr sand(new AgentInet4McRtSandesh(vrf, context(), "",
301 0 : get_stale()));
302 0 : boost::system::error_code ec;
303 0 : Ip4Address zero_addr = IpAddress::from_string("0.0.0.0", ec).to_v4();
304 0 : Ip4Address src_ip, grp_ip;
305 0 : if (get_src_ip().empty()) {
306 0 : src_ip = zero_addr;
307 : } else {
308 0 : src_ip = Ip4Address::from_string(get_src_ip(), ec);
309 : }
310 0 : if (get_grp_ip().empty()) {
311 0 : sand.reset(new AgentInet4McRtSandesh(vrf, context(), "", get_stale()));
312 : } else {
313 0 : grp_ip = Ip4Address::from_string(get_grp_ip(), ec);
314 0 : sand.reset(new AgentInet4McRtSandesh(vrf, context(), "", src_ip,
315 0 : grp_ip, get_stale()));
316 : }
317 0 : sand->DoSandesh(sand);
318 0 : }
319 :
320 0 : AgentSandeshPtr Inet4MulticastAgentRouteTable::GetAgentSandesh
321 : (const AgentSandeshArguments *args, const std::string &context) {
322 0 : return AgentSandeshPtr(new AgentInet4McRtSandesh(vrf_entry(), context, "",
323 0 : false));
324 : }
|