VOM: vhost-use interfaces
[vpp.git] / src / vpp-api / vom / interface_cmds.cpp
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include "vom/interface_cmds.hpp"
17 #include "vom/cmd.hpp"
18
19 DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
20 DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
21 DEFINE_VAPI_MSG_IDS_AF_PACKET_API_JSON;
22 DEFINE_VAPI_MSG_IDS_TAP_API_JSON;
23 DEFINE_VAPI_MSG_IDS_VHOST_USER_API_JSON;
24 DEFINE_VAPI_MSG_IDS_STATS_API_JSON;
25
26 namespace VOM {
27 namespace interface_cmds {
28 loopback_create_cmd::loopback_create_cmd(HW::item<handle_t>& item,
29                                          const std::string& name)
30   : create_cmd(item, name)
31 {
32 }
33
34 rc_t
35 loopback_create_cmd::issue(connection& con)
36 {
37   msg_t req(con.ctx(), std::ref(*this));
38
39   VAPI_CALL(req.execute());
40
41   m_hw_item = wait();
42
43   if (m_hw_item.rc() == rc_t::OK) {
44     insert_interface();
45   }
46
47   return rc_t::OK;
48 }
49 std::string
50 loopback_create_cmd::to_string() const
51 {
52   std::ostringstream s;
53   s << "loopback-itf-create: " << m_hw_item.to_string() << " name:" << m_name;
54
55   return (s.str());
56 }
57
58 af_packet_create_cmd::af_packet_create_cmd(HW::item<handle_t>& item,
59                                            const std::string& name)
60   : create_cmd(item, name)
61 {
62 }
63
64 rc_t
65 af_packet_create_cmd::issue(connection& con)
66 {
67   msg_t req(con.ctx(), std::ref(*this));
68
69   auto& payload = req.get_request().get_payload();
70
71   payload.use_random_hw_addr = 1;
72   memset(payload.host_if_name, 0, sizeof(payload.host_if_name));
73   memcpy(payload.host_if_name, m_name.c_str(),
74          std::min(m_name.length(), sizeof(payload.host_if_name)));
75
76   VAPI_CALL(req.execute());
77
78   m_hw_item = wait();
79
80   if (m_hw_item.rc() == rc_t::OK) {
81     insert_interface();
82   }
83
84   return rc_t::OK;
85 }
86 std::string
87 af_packet_create_cmd::to_string() const
88 {
89   std::ostringstream s;
90   s << "af-packet-itf-create: " << m_hw_item.to_string() << " name:" << m_name;
91
92   return (s.str());
93 }
94
95 tap_create_cmd::tap_create_cmd(HW::item<handle_t>& item,
96                                const std::string& name)
97   : create_cmd(item, name)
98 {
99 }
100
101 rc_t
102 tap_create_cmd::issue(connection& con)
103 {
104   msg_t req(con.ctx(), std::ref(*this));
105
106   auto& payload = req.get_request().get_payload();
107
108   memset(payload.tap_name, 0, sizeof(payload.tap_name));
109   memcpy(payload.tap_name, m_name.c_str(),
110          std::min(m_name.length(), sizeof(payload.tap_name)));
111   payload.use_random_mac = 1;
112
113   VAPI_CALL(req.execute());
114
115   m_hw_item = wait();
116
117   if (m_hw_item.rc() == rc_t::OK) {
118     insert_interface();
119   }
120
121   return rc_t::OK;
122 }
123
124 std::string
125 tap_create_cmd::to_string() const
126 {
127   std::ostringstream s;
128   s << "tap-intf-create: " << m_hw_item.to_string() << " name:" << m_name;
129
130   return (s.str());
131 }
132
133 vhost_create_cmd::vhost_create_cmd(HW::item<handle_t>& item,
134                                    const std::string& name,
135                                    const std::string& tag)
136   : create_cmd(item, name)
137   , m_tag(tag)
138 {
139 }
140
141 rc_t
142 vhost_create_cmd::issue(connection& con)
143 {
144   msg_t req(con.ctx(), std::ref(*this));
145
146   auto& payload = req.get_request().get_payload();
147   memset(payload.sock_filename, 0, sizeof(payload.sock_filename));
148   memcpy(payload.sock_filename, m_name.c_str(),
149          std::min(m_name.length(), sizeof(payload.sock_filename)));
150   memset(payload.tag, 0, sizeof(payload.tag));
151
152   if (!m_tag.empty())
153     memcpy(payload.tag, m_tag.c_str(),
154            std::min(m_tag.length(), sizeof(payload.tag)));
155
156   payload.is_server = 1;
157   payload.use_custom_mac = 0;
158   payload.renumber = 0;
159
160   VAPI_CALL(req.execute());
161
162   m_hw_item = wait();
163
164   return rc_t::OK;
165 }
166
167 std::string
168 vhost_create_cmd::to_string() const
169 {
170   std::ostringstream s;
171   s << "vhost-intf-create: " << m_hw_item.to_string() << " name:" << m_name
172     << " tag:" << m_tag;
173
174   return (s.str());
175 }
176
177 loopback_delete_cmd::loopback_delete_cmd(HW::item<handle_t>& item)
178   : delete_cmd(item)
179 {
180 }
181
182 rc_t
183 loopback_delete_cmd::issue(connection& con)
184 {
185   msg_t req(con.ctx(), std::ref(*this));
186
187   auto& payload = req.get_request().get_payload();
188   payload.sw_if_index = m_hw_item.data().value();
189
190   VAPI_CALL(req.execute());
191
192   wait();
193   m_hw_item.set(rc_t::NOOP);
194
195   remove_interface();
196   return rc_t::OK;
197 }
198
199 std::string
200 loopback_delete_cmd::to_string() const
201 {
202   std::ostringstream s;
203   s << "loopback-itf-delete: " << m_hw_item.to_string();
204
205   return (s.str());
206 }
207
208 af_packet_delete_cmd::af_packet_delete_cmd(HW::item<handle_t>& item,
209                                            const std::string& name)
210   : delete_cmd(item, name)
211 {
212 }
213
214 rc_t
215 af_packet_delete_cmd::issue(connection& con)
216 {
217   msg_t req(con.ctx(), std::ref(*this));
218
219   auto& payload = req.get_request().get_payload();
220   memset(payload.host_if_name, 0, sizeof(payload.host_if_name));
221   memcpy(payload.host_if_name, m_name.c_str(),
222          std::min(m_name.length(), sizeof(payload.host_if_name)));
223
224   VAPI_CALL(req.execute());
225
226   wait();
227   m_hw_item.set(rc_t::NOOP);
228
229   remove_interface();
230   return rc_t::OK;
231 }
232 std::string
233 af_packet_delete_cmd::to_string() const
234 {
235   std::ostringstream s;
236   s << "af_packet-itf-delete: " << m_hw_item.to_string();
237
238   return (s.str());
239 }
240
241 tap_delete_cmd::tap_delete_cmd(HW::item<handle_t>& item)
242   : delete_cmd(item)
243 {
244 }
245
246 rc_t
247 tap_delete_cmd::issue(connection& con)
248 {
249   // finally... call VPP
250
251   remove_interface();
252   return rc_t::OK;
253 }
254 std::string
255 tap_delete_cmd::to_string() const
256 {
257   std::ostringstream s;
258   s << "tap-itf-delete: " << m_hw_item.to_string();
259
260   return (s.str());
261 }
262
263 vhost_delete_cmd::vhost_delete_cmd(HW::item<handle_t>& item,
264                                    const std::string& name)
265   : delete_cmd(item, name)
266 {
267 }
268
269 rc_t
270 vhost_delete_cmd::issue(connection& con)
271 {
272   msg_t req(con.ctx(), std::ref(*this));
273
274   auto& payload = req.get_request().get_payload();
275   payload.sw_if_index = m_hw_item.data().value();
276
277   VAPI_CALL(req.execute());
278
279   wait();
280
281   return rc_t::OK;
282 }
283 std::string
284 vhost_delete_cmd::to_string() const
285 {
286   std::ostringstream s;
287   s << "vhost-itf-delete: " << m_hw_item.to_string() << " name:" << m_name;
288
289   return (s.str());
290 }
291
292 state_change_cmd::state_change_cmd(HW::item<interface::admin_state_t>& state,
293                                    const HW::item<handle_t>& hdl)
294   : rpc_cmd(state)
295   , m_hdl(hdl)
296 {
297 }
298
299 bool
300 state_change_cmd::operator==(const state_change_cmd& other) const
301 {
302   return ((m_hdl == other.m_hdl) && (m_hw_item == other.m_hw_item));
303 }
304
305 rc_t
306 state_change_cmd::issue(connection& con)
307 {
308   msg_t req(con.ctx(), std::ref(*this));
309
310   auto& payload = req.get_request().get_payload();
311   payload.sw_if_index = m_hdl.data().value();
312   payload.admin_up_down = m_hw_item.data().value();
313
314   VAPI_CALL(req.execute());
315
316   m_hw_item.set(wait());
317
318   return rc_t::OK;
319 }
320
321 std::string
322 state_change_cmd::to_string() const
323 {
324   std::ostringstream s;
325   s << "itf-state-change: " << m_hw_item.to_string()
326     << " hdl:" << m_hdl.to_string();
327   return (s.str());
328 }
329
330 set_table_cmd::set_table_cmd(HW::item<route::table_id_t>& table,
331                              const l3_proto_t& proto,
332                              const HW::item<handle_t>& hdl)
333   : rpc_cmd(table)
334   , m_hdl(hdl)
335   , m_proto(proto)
336 {
337 }
338
339 bool
340 set_table_cmd::operator==(const set_table_cmd& other) const
341 {
342   return ((m_hdl == other.m_hdl) && (m_proto == other.m_proto) &&
343           (m_hw_item == other.m_hw_item));
344 }
345
346 rc_t
347 set_table_cmd::issue(connection& con)
348 {
349   msg_t req(con.ctx(), std::ref(*this));
350
351   auto& payload = req.get_request().get_payload();
352   payload.sw_if_index = m_hdl.data().value();
353   payload.is_ipv6 = m_proto.is_ipv6();
354   payload.vrf_id = m_hw_item.data();
355
356   VAPI_CALL(req.execute());
357
358   m_hw_item.set(wait());
359
360   return (rc_t::OK);
361 }
362
363 std::string
364 set_table_cmd::to_string() const
365 {
366   std::ostringstream s;
367   s << "itf-set-table: " << m_hw_item.to_string()
368     << " proto:" << m_proto.to_string() << " hdl:" << m_hdl.to_string();
369   return (s.str());
370 }
371
372 set_mac_cmd::set_mac_cmd(HW::item<l2_address_t>& mac,
373                          const HW::item<handle_t>& hdl)
374   : rpc_cmd(mac)
375   , m_hdl(hdl)
376 {
377 }
378
379 bool
380 set_mac_cmd::operator==(const set_mac_cmd& other) const
381 {
382   return ((m_hdl == other.m_hdl) && (m_hw_item == other.m_hw_item));
383 }
384
385 rc_t
386 set_mac_cmd::issue(connection& con)
387 {
388   msg_t req(con.ctx(), std::ref(*this));
389
390   auto& payload = req.get_request().get_payload();
391   payload.sw_if_index = m_hdl.data().value();
392   m_hw_item.data().to_mac().to_bytes(payload.mac_address,
393                                      sizeof(payload.mac_address));
394
395   VAPI_CALL(req.execute());
396
397   m_hw_item.set(wait());
398
399   return (rc_t::OK);
400 }
401
402 std::string
403 set_mac_cmd::to_string() const
404 {
405   std::ostringstream s;
406   s << "itf-set-mac: " << m_hw_item.to_string() << " hdl:" << m_hdl.to_string();
407   return (s.str());
408 }
409
410 events_cmd::events_cmd(interface::event_listener& el)
411   : event_cmd(el.status())
412   , m_listener(el)
413 {
414 }
415
416 bool
417 events_cmd::operator==(const events_cmd& other) const
418 {
419   return (true);
420 }
421
422 rc_t
423 events_cmd::issue(connection& con)
424 {
425   /*
426  * First set the call back to handle the interface events
427  */
428   m_reg.reset(new reg_t(con.ctx(), std::ref(*(static_cast<event_cmd*>(this)))));
429
430   /*
431  * then send the request to enable them
432  */
433   msg_t req(con.ctx(), std::ref(*(static_cast<rpc_cmd*>(this))));
434
435   auto& payload = req.get_request().get_payload();
436   payload.enable_disable = 1;
437   payload.pid = getpid();
438
439   VAPI_CALL(req.execute());
440
441   wait();
442
443   return (rc_t::OK);
444 }
445
446 void
447 events_cmd::retire(connection& con)
448 {
449   /*
450  * disable interface events.
451  */
452   msg_t req(con.ctx(), std::ref(*(static_cast<rpc_cmd*>(this))));
453
454   auto& payload = req.get_request().get_payload();
455   payload.enable_disable = 0;
456   payload.pid = getpid();
457
458   VAPI_CALL(req.execute());
459
460   wait();
461 }
462
463 void
464 events_cmd::notify()
465 {
466   m_listener.handle_interface_event(this);
467 }
468
469 std::string
470 events_cmd::to_string() const
471 {
472   return ("itf-events");
473 }
474
475 /**
476  * Interface statistics
477  */
478 stats_enable_cmd::stats_enable_cmd(interface::stat_listener& el,
479                                    const handle_t& handle)
480   : event_cmd(el.status())
481   , m_listener(el)
482   , m_swifindex(handle)
483 {
484 }
485
486 bool
487 stats_enable_cmd::operator==(const stats_enable_cmd& other) const
488 {
489   return (true);
490 }
491
492 rc_t
493 stats_enable_cmd::issue(connection& con)
494 {
495   /*
496    * First set the call back to handle the interface stats
497    */
498   m_reg.reset(new reg_t(con.ctx(), std::ref(*(static_cast<event_cmd*>(this)))));
499
500   /*
501    * then send the request to enable them
502    */
503   msg_t req(con.ctx(), 1, std::ref(*(static_cast<rpc_cmd*>(this))));
504
505   auto& payload = req.get_request().get_payload();
506   payload.enable_disable = 1;
507   payload.pid = getpid();
508   payload.num = 1;
509
510   payload.sw_ifs[0] = m_swifindex.value();
511
512   VAPI_CALL(req.execute());
513
514   wait();
515
516   return (rc_t::OK);
517 }
518
519 void
520 stats_enable_cmd::retire(connection& con)
521 {
522   /*
523    * disable interface stats.
524    */
525   msg_t req(con.ctx(), 1, std::ref(*(static_cast<rpc_cmd*>(this))));
526
527   auto& payload = req.get_request().get_payload();
528   payload.enable_disable = 0;
529   payload.pid = getpid();
530   payload.num = 1;
531   payload.sw_ifs[0] = m_swifindex.value();
532
533   VAPI_CALL(req.execute());
534
535   wait();
536 }
537
538 void
539 stats_enable_cmd::notify()
540 {
541   m_listener.handle_interface_stat(this);
542 }
543
544 std::string
545 stats_enable_cmd::to_string() const
546 {
547   std::ostringstream s;
548   s << "itf-stats-enable itf:" << m_swifindex.to_string();
549   return (s.str());
550 }
551
552 stats_disable_cmd::stats_disable_cmd(const handle_t& handle)
553   : rpc_cmd(m_res)
554   , m_swifindex(handle)
555 {
556 }
557
558 bool
559 stats_disable_cmd::operator==(const stats_disable_cmd& other) const
560 {
561   return (true);
562 }
563
564 rc_t
565 stats_disable_cmd::issue(connection& con)
566 {
567   /*
568    * then send the request to enable them
569    */
570   msg_t req(con.ctx(), 1, std::ref(*this));
571
572   auto& payload = req.get_request().get_payload();
573   payload.enable_disable = 0;
574   payload.pid = getpid();
575   payload.num = 1;
576
577   payload.sw_ifs[0] = m_swifindex.value();
578
579   VAPI_CALL(req.execute());
580
581   wait();
582
583   return (rc_t::OK);
584 }
585
586 std::string
587 stats_disable_cmd::to_string() const
588 {
589   std::ostringstream s;
590   s << "itf-stats-disable itf:" << m_swifindex.to_string();
591   return (s.str());
592 }
593
594 dump_cmd::dump_cmd()
595 {
596 }
597
598 bool
599 dump_cmd::operator==(const dump_cmd& other) const
600 {
601   return (true);
602 }
603
604 rc_t
605 dump_cmd::issue(connection& con)
606 {
607   m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
608
609   auto& payload = m_dump->get_request().get_payload();
610   payload.name_filter_valid = 0;
611
612   VAPI_CALL(m_dump->execute());
613
614   wait();
615
616   return rc_t::OK;
617 }
618
619 std::string
620 dump_cmd::to_string() const
621 {
622   return ("itf-dump");
623 }
624
625 vhost_dump_cmd::vhost_dump_cmd()
626 {
627 }
628
629 bool
630 vhost_dump_cmd::operator==(const vhost_dump_cmd& other) const
631 {
632   return (true);
633 }
634
635 rc_t
636 vhost_dump_cmd::issue(connection& con)
637 {
638   m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
639
640   VAPI_CALL(m_dump->execute());
641
642   wait();
643
644   return rc_t::OK;
645 }
646
647 std::string
648 vhost_dump_cmd::to_string() const
649 {
650   return ("vhost-itf-dump");
651 }
652
653 set_tag::set_tag(HW::item<handle_t>& item, const std::string& name)
654   : rpc_cmd(item)
655   , m_name(name)
656 {
657 }
658
659 rc_t
660 set_tag::issue(connection& con)
661 {
662   msg_t req(con.ctx(), std::ref(*this));
663
664   auto& payload = req.get_request().get_payload();
665   payload.is_add = 1;
666   payload.sw_if_index = m_hw_item.data().value();
667   memcpy(payload.tag, m_name.c_str(), m_name.length());
668
669   VAPI_CALL(req.execute());
670
671   wait();
672
673   return rc_t::OK;
674 }
675 std::string
676 set_tag::to_string() const
677 {
678   std::ostringstream s;
679   s << "itf-set-tag: " << m_hw_item.to_string() << " name:" << m_name;
680
681   return (s.str());
682 }
683
684 bool
685 set_tag::operator==(const set_tag& o) const
686 {
687   return ((m_name == o.m_name) && (m_hw_item.data() == o.m_hw_item.data()));
688 }
689 }; // namespace interface_cmds
690 }; // namespace VOM
691
692 /*
693  * fd.io coding-style-patch-verification: ON
694  *
695  * Local Variables:
696  * eval: (c-set-style "mozilla")
697  * End:
698  */