5b03f5db02110c48e416719ec701f1d49d408de2
[vpp.git] / src / vpp-api / vom / acl_list.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/acl_list.hpp"
17 #include "vom/acl_list_cmds.hpp"
18 #include "vom/logger.hpp"
19
20 namespace VOM {
21 namespace ACL {
22
23 template <>
24 l2_list::event_handler::event_handler()
25 {
26   OM::register_listener(this);
27   inspect::register_handler({ "l2-acl-list" }, "L2 ACL lists", this);
28 }
29
30 template <>
31 void
32 l2_list::event_handler::handle_populate(const client_db::key_t& key)
33 {
34   /* hack to get this function instantiated */
35   m_evh.order();
36
37   /*
38    * dump VPP Bridge domains
39    */
40   std::shared_ptr<list_cmds::l2_dump_cmd> cmd =
41     std::make_shared<list_cmds::l2_dump_cmd>();
42
43   HW::enqueue(cmd);
44   HW::write();
45
46   for (auto& record : *cmd) {
47     auto& payload = record.get_payload();
48
49     const handle_t hdl(payload.acl_index);
50     l2_list acl(hdl, std::string(reinterpret_cast<const char*>(payload.tag)));
51
52     for (unsigned int ii = 0; ii < payload.count; ii++) {
53       const route::prefix_t pfx(payload.r[ii].is_ipv6,
54                                 payload.r[ii].src_ip_addr,
55                                 payload.r[ii].src_ip_prefix_len);
56       l2_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), pfx,
57                    { payload.r[ii].src_mac }, { payload.r[ii].src_mac_mask });
58
59       acl.insert(rule);
60     }
61     VOM_LOG(log_level_t::DEBUG) << "dump: " << acl.to_string();
62
63     /*
64      * Write each of the discovered ACLs into the OM,
65      * but disable the HW Command q whilst we do, so that no
66      * commands are sent to VPP
67      */
68     OM::commit(key, acl);
69   }
70 }
71
72 template <>
73 l3_list::event_handler::event_handler()
74 {
75   OM::register_listener(this);
76   inspect::register_handler({ "l3-acl-list" }, "L3 ACL lists", this);
77 }
78
79 template <>
80 void
81 l3_list::event_handler::handle_populate(const client_db::key_t& key)
82 {
83   /* hack to get this function instantiated */
84   m_evh.order();
85
86   /*
87    * dump L3 ACLs Bridge domains
88    */
89   std::shared_ptr<list_cmds::l3_dump_cmd> cmd =
90     std::make_shared<list_cmds::l3_dump_cmd>();
91
92   HW::enqueue(cmd);
93   HW::write();
94
95   for (auto& record : *cmd) {
96     auto& payload = record.get_payload();
97
98     const handle_t hdl(payload.acl_index);
99     l3_list acl(hdl, std::string(reinterpret_cast<const char*>(payload.tag)));
100
101     for (unsigned int ii = 0; ii < payload.count; ii++) {
102       const route::prefix_t src(payload.r[ii].is_ipv6,
103                                 payload.r[ii].src_ip_addr,
104                                 payload.r[ii].src_ip_prefix_len);
105       const route::prefix_t dst(payload.r[ii].is_ipv6,
106                                 payload.r[ii].dst_ip_addr,
107                                 payload.r[ii].dst_ip_prefix_len);
108       l3_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), src, dst);
109
110       rule.set_proto(payload.r[ii].proto);
111       rule.set_src_from_port(payload.r[ii].srcport_or_icmptype_first);
112       rule.set_src_to_port(payload.r[ii].srcport_or_icmptype_last);
113       rule.set_dst_from_port(payload.r[ii].dstport_or_icmpcode_first);
114       rule.set_dst_to_port(payload.r[ii].dstport_or_icmpcode_last);
115       rule.set_tcp_flags_mask(payload.r[ii].tcp_flags_mask);
116       rule.set_tcp_flags_value(payload.r[ii].tcp_flags_value);
117
118       acl.insert(rule);
119     }
120     VOM_LOG(log_level_t::DEBUG) << "dump: " << acl.to_string();
121
122     /*
123      * Write each of the discovered ACLs into the OM,
124      * but disable the HW Command q whilst we do, so that no
125      * commands are sent to VPP
126      */
127     OM::commit(key, acl);
128   }
129 }
130
131 template <>
132 void
133 l3_list::update(const l3_list& obj)
134 {
135   /*
136    * always update the instance with the latest rule set
137    */
138   if (rc_t::OK != m_hdl.rc() || obj.m_rules != m_rules) {
139     HW::enqueue(new list_cmds::l3_update_cmd(m_hdl, m_key, m_rules));
140   }
141   /*
142    * We don't, can't, read the priority from VPP,
143    * so the is equals check above does not include the priorty.
144    * but we save it now.
145    */
146   m_rules = obj.m_rules;
147 }
148 template <>
149 void
150 l2_list::update(const l2_list& obj)
151 {
152   /*
153    * always update the instance with the latest rule set
154    */
155   if (rc_t::OK != m_hdl.rc() || obj.m_rules != m_rules) {
156     HW::enqueue(new list_cmds::l2_update_cmd(m_hdl, m_key, m_rules));
157   }
158   /*
159    * We don't, can't, read the priority from VPP,
160    * so the is equals check above does not include the priorty.
161    * but we save it now.
162    */
163   m_rules = obj.m_rules;
164 }
165 /**
166  * Sweep/reap the object if still stale
167  */
168 template <>
169 void
170 l3_list::sweep(void)
171 {
172   if (m_hdl) {
173     HW::enqueue(new list_cmds::l3_delete_cmd(m_hdl));
174   }
175   HW::write();
176 }
177 template <>
178 void
179 l2_list::sweep(void)
180 {
181   if (m_hdl) {
182     HW::enqueue(new list_cmds::l2_delete_cmd(m_hdl));
183   }
184   HW::write();
185 }
186
187 /**
188  * Replay the objects state to HW
189  */
190 template <>
191 void
192 l3_list::replay(void)
193 {
194   if (m_hdl) {
195     m_hdl.data().reset();
196     HW::enqueue(new list_cmds::l3_update_cmd(m_hdl, m_key, m_rules));
197   }
198 }
199 template <>
200 void
201 l2_list::replay(void)
202 {
203   if (m_hdl) {
204     m_hdl.data().reset();
205     HW::enqueue(new list_cmds::l2_update_cmd(m_hdl, m_key, m_rules));
206   }
207 }
208
209 }; // namespace ACL
210 }; // namespace VOM
211
212 /*
213  * fd.io coding-style-patch-verification: ON
214  *
215  * Local Variables:
216  * eval: (c-set-style "mozilla")
217  * End:
218  */