A bit of buffer metadata reshuffling to accommodate flow_id
[vpp.git] / src / vpp-api / vom / l2_binding.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/l2_binding.hpp"
17 #include "vom/l2_binding_cmds.hpp"
18 #include "vom/singular_db_funcs.hpp"
19
20 namespace VOM {
21 /**
22  * A DB of all the L2 Configs
23  */
24 singular_db<l2_binding::key_t, l2_binding> l2_binding::m_db;
25
26 l2_binding::event_handler l2_binding::m_evh;
27
28 /*
29  * Make sure these are in sync with the smae enum in VPP
30  */
31 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_DISABLED(
32   0,
33   "disabled");
34 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_PUSH_1(1,
35                                                                      "push-1");
36 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_PUSH_2(2,
37                                                                      "push-2");
38 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_POP_1(3, "pop-1");
39 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_POP_2(4, "pop-2");
40 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_1_1(
41   5,
42   "translate-1-1");
43 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_1_2(
44   6,
45   "translate-1-2");
46 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_2_1(
47   7,
48   "translate-2-1");
49 const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_2_2(
50   5,
51   "translate-2-2");
52
53 l2_binding::l2_vtr_op_t::l2_vtr_op_t(int v, const std::string s)
54   : enum_base<l2_binding::l2_vtr_op_t>(v, s)
55 {
56 }
57
58 /**
59  * Construct a new object matching the desried state
60  */
61 l2_binding::l2_binding(const interface& itf, const bridge_domain& bd)
62   : m_itf(itf.singular())
63   , m_bd(bd.singular())
64   , m_binding(0)
65   , m_vtr_op(l2_vtr_op_t::L2_VTR_DISABLED, rc_t::UNSET)
66   , m_vtr_op_tag(0)
67 {
68 }
69
70 l2_binding::l2_binding(const l2_binding& o)
71   : m_itf(o.m_itf)
72   , m_bd(o.m_bd)
73   , m_binding(0)
74   , m_vtr_op(o.m_vtr_op)
75   , m_vtr_op_tag(o.m_vtr_op_tag)
76 {
77 }
78
79 const l2_binding::key_t&
80 l2_binding::key() const
81 {
82   return (m_itf->key());
83 }
84
85 bool
86 l2_binding::operator==(const l2_binding& l) const
87 {
88   return ((*m_itf == *l.m_itf) && (*m_bd == *l.m_bd));
89 }
90
91 std::shared_ptr<l2_binding>
92 l2_binding::find(const key_t& key)
93 {
94   return (m_db.find(key));
95 }
96
97 void
98 l2_binding::sweep()
99 {
100   if (m_binding && handle_t::INVALID != m_itf->handle()) {
101     HW::enqueue(
102       new l2_binding_cmds::unbind_cmd(m_binding, m_itf->handle(), m_bd->id(),
103                                       interface::type_t::BVI == m_itf->type()));
104   }
105
106   // no need to undo the VTR operation.
107   HW::write();
108 }
109
110 void
111 l2_binding::replay()
112 {
113   if (m_binding && handle_t::INVALID != m_itf->handle()) {
114     HW::enqueue(
115       new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(), m_bd->id(),
116                                     interface::type_t::BVI == m_itf->type()));
117   }
118
119   if (m_vtr_op && handle_t::INVALID != m_itf->handle()) {
120     HW::enqueue(new l2_binding_cmds::set_vtr_op_cmd(m_vtr_op, m_itf->handle(),
121                                                     m_vtr_op_tag));
122   }
123 }
124
125 l2_binding::~l2_binding()
126 {
127   sweep();
128
129   // not in the DB anymore.
130   m_db.release(m_itf->key(), this);
131 }
132
133 std::string
134 l2_binding::to_string() const
135 {
136   std::ostringstream s;
137   s << "L2-binding:[" << m_itf->to_string() << " " << m_bd->to_string() << " "
138     << m_binding.to_string() << "]";
139
140   return (s.str());
141 }
142
143 void
144 l2_binding::set(const l2_vtr_op_t& op, uint16_t tag)
145 {
146   assert(rc_t::UNSET == m_vtr_op.rc());
147   m_vtr_op.set(rc_t::NOOP);
148   m_vtr_op.update(op);
149   m_vtr_op_tag = tag;
150 }
151
152 void
153 l2_binding::update(const l2_binding& desired)
154 {
155   /*
156    * the desired state is always that the interface should be created
157    */
158   if (rc_t::OK != m_binding.rc()) {
159     HW::enqueue(
160       new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(), m_bd->id(),
161                                     interface::type_t::BVI == m_itf->type()));
162   } else if (!(*m_bd == *desired.m_bd)) {
163     /*
164      * re-binding to a different BD. do unbind, bind.
165      */
166     HW::enqueue(
167       new l2_binding_cmds::unbind_cmd(m_binding, m_itf->handle(), m_bd->id(),
168                                       interface::type_t::BVI == m_itf->type()));
169     m_bd = desired.m_bd;
170     HW::enqueue(
171       new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(), m_bd->id(),
172                                     interface::type_t::BVI == m_itf->type()));
173   }
174
175   /*
176    * set the VTR operation if request
177    */
178   if (m_vtr_op.update(desired.m_vtr_op)) {
179     HW::enqueue(new l2_binding_cmds::set_vtr_op_cmd(m_vtr_op, m_itf->handle(),
180                                                     m_vtr_op_tag));
181   }
182 }
183
184 std::shared_ptr<l2_binding>
185 l2_binding::find_or_add(const l2_binding& temp)
186 {
187   return (m_db.find_or_add(temp.m_itf->key(), temp));
188 }
189
190 std::shared_ptr<l2_binding>
191 l2_binding::singular() const
192 {
193   return find_or_add(*this);
194 }
195
196 void
197 l2_binding::dump(std::ostream& os)
198 {
199   db_dump(m_db, os);
200 }
201
202 l2_binding::event_handler::event_handler()
203 {
204   OM::register_listener(this);
205   inspect::register_handler({ "l2" }, "L2 bindings", this);
206 }
207
208 void
209 l2_binding::event_handler::handle_replay()
210 {
211   m_db.replay();
212 }
213
214 void
215 l2_binding::event_handler::handle_populate(const client_db::key_t& key)
216 {
217   /**
218    * This is done while populating the bridge-domain
219    */
220 }
221
222 dependency_t
223 l2_binding::event_handler::order() const
224 {
225   return (dependency_t::BINDING);
226 }
227
228 void
229 l2_binding::event_handler::show(std::ostream& os)
230 {
231   db_dump(m_db, os);
232 }
233 }
234
235 /*
236  * fd.io coding-style-patch-verification: ON
237  *
238  * Local Variables:
239  * eval: (c-set-style "mozilla")
240  * End:
241  */