bmv2
Designing your own switch target with bmv2
Loading...
Searching...
No Matches
action_profile.h
1/* Copyright 2013-present Barefoot Networks, Inc.
2 *
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/*
17 * Antonin Bas (antonin@barefootnetworks.com)
18 *
19 */
20
21#ifndef BM_BM_SIM_ACTION_PROFILE_H_
22#define BM_BM_SIM_ACTION_PROFILE_H_
23
24#include <iosfwd>
25#include <memory>
26#include <string>
27#include <utility>
28#include <vector>
29
30// shared_mutex will only be available in C++-14, so for now I'm using boost
31#include <boost/thread/shared_mutex.hpp>
32
33#include "action_entry.h"
34#include "calculations.h"
35#include "handle_mgr.h"
36#include "match_error_codes.h"
37#include "ras.h"
38
39namespace bm {
40
41class ActionProfile : public NamedP4Object {
42 friend class MatchTableIndirect;
43 friend class MatchTableIndirectWS;
44
45 public:
46 using mbr_hdl_t = uint32_t;
47 using grp_hdl_t = uint32_t;
48
49 using hash_t = unsigned int;
50
51 class IndirectIndex {
52 public:
53 IndirectIndex() { }
54
55 bool is_mbr() const { return ((index >> 24) == _mbr); }
56 bool is_grp() const { return ((index >> 24) == _grp); }
57 unsigned int get() const { return (index & _index_mask); }
58 unsigned int get_mbr() const { assert(is_mbr()); return get(); }
59 unsigned int get_grp() const { assert(is_grp()); return get(); }
60
61 void dump(std::ostream *stream) const {
62 if (is_grp())
63 (*stream) << "group(" << get() << ")";
64 else
65 (*stream) << "member(" << get() << ")";
66 }
67
68 friend std::ostream& operator<<(std::ostream &out, const IndirectIndex &i) {
69 i.dump(&out);
70 return out;
71 }
72
73 void serialize(std::ostream *out) const;
74 void deserialize(std::istream *in, const P4Objects &objs);
75
76 static IndirectIndex make_mbr_index(unsigned int index) {
77 assert(index <= _index_mask);
78 return IndirectIndex((_mbr << 24) | index);
79 }
80
81 static IndirectIndex make_grp_index(unsigned int index) {
82 assert(index <= _index_mask);
83 return IndirectIndex((_grp << 24) | index);
84 }
85
86 private:
87 explicit IndirectIndex(unsigned int index) : index(index) { }
88
89 static const unsigned char _mbr = 0x00;
90 static const unsigned char _grp = 0x01;
91 static const unsigned int _index_mask = 0x00FFFFFF;
92
93 unsigned int index{0};
94 };
95
96 struct Member {
97 mbr_hdl_t mbr;
98 const ActionFn *action_fn;
99 ActionData action_data;
100 };
101
102 struct Group {
103 grp_hdl_t grp;
104 std::vector<mbr_hdl_t> mbr_handles;
105 };
106
107 class GroupSelectionIface {
108 public:
109 virtual ~GroupSelectionIface() { }
110
111 virtual void add_member_to_group(grp_hdl_t grp, mbr_hdl_t mbr) = 0;
112 virtual void remove_member_from_group(grp_hdl_t grp, mbr_hdl_t mbr) = 0;
113 virtual mbr_hdl_t get_from_hash(grp_hdl_t grp, hash_t h) const = 0;
114 virtual void reset() = 0;
115 };
116
117 ActionProfile(const std::string &name, p4object_id_t id, bool with_selection);
118
119 bool has_selection() const;
120
121 void set_hash(std::unique_ptr<Calculation> h) {
122 hash = std::move(h);
123 }
124
125 // give the target some control over the member selection process
126 void set_group_selector(std::shared_ptr<GroupSelectionIface> selector);
127
128 // runtime interface
129
130 MatchErrorCode add_member(const ActionFn *action_fn,
131 ActionData action_data, // move it
132 mbr_hdl_t *mbr);
133
134 MatchErrorCode delete_member(mbr_hdl_t mbr);
135
136 MatchErrorCode modify_member(mbr_hdl_t mbr,
137 const ActionFn *action_fn,
138 ActionData action_data);
139
140 MatchErrorCode create_group(grp_hdl_t *grp);
141
142 MatchErrorCode delete_group(grp_hdl_t grp);
143
144 MatchErrorCode add_member_to_group(mbr_hdl_t mbr, grp_hdl_t grp);
145
146 MatchErrorCode remove_member_from_group(mbr_hdl_t mbr, grp_hdl_t grp);
147
148 // end of runtime interface
149
150 MatchErrorCode get_member(mbr_hdl_t mbr, Member *member) const;
151
152 std::vector<Member> get_members() const;
153
154 MatchErrorCode get_group(grp_hdl_t grp, Group *group) const;
155
156 std::vector<Group> get_groups() const;
157
158 size_t get_num_members() const;
159 size_t get_num_groups() const;
160
161 MatchErrorCode get_num_members_in_group(grp_hdl_t grp, size_t *nb) const;
162
163 void reset_state();
164
165 void serialize(std::ostream *out) const;
166 void deserialize(std::istream *in, const P4Objects &objs);
167
168 private:
169 using ReadLock = boost::shared_lock<boost::shared_mutex>;
170 using WriteLock = boost::unique_lock<boost::shared_mutex>;
171
172 class IndirectIndexRefCount {
173 public:
174 using count_t = unsigned int;
175
176 public:
177 void set(const IndirectIndex &index, count_t value) {
178 unsigned int i = index.get();
179 auto &v = (index.is_mbr()) ? mbr_count : grp_count;
180 assert(i <= v.size());
181 if (i == v.size())
182 v.push_back(value);
183 else
184 v[i] = value;
185 }
186
187 count_t get(const IndirectIndex &index) const {
188 unsigned int i = index.get();
189 return (index.is_mbr()) ? mbr_count[i] : grp_count[i];
190 }
191
192 void increase(const IndirectIndex &index) {
193 unsigned int i = index.get();
194 if (index.is_mbr())
195 mbr_count[i]++;
196 else
197 grp_count[i]++;
198 }
199
200 void decrease(const IndirectIndex &index) {
201 unsigned int i = index.get();
202 if (index.is_mbr())
203 mbr_count[i]--;
204 else
205 grp_count[i]--;
206 }
207
208 void serialize(std::ostream *out) const;
209 void deserialize(std::istream *in);
210
211 private:
212 std::vector<count_t> mbr_count{};
213 std::vector<count_t> grp_count{};
214 };
215
216 class GroupInfo {
217 public:
218 using iterator = RandAccessUIntSet::iterator;
219 using const_iterator = RandAccessUIntSet::const_iterator;
220
221 MatchErrorCode add_member(mbr_hdl_t mbr);
222 MatchErrorCode delete_member(mbr_hdl_t mbr);
223 bool contains_member(mbr_hdl_t mbr) const;
224 size_t size() const;
225 mbr_hdl_t get_nth(size_t n) const;
226
227 // iterators
228 iterator begin() { return mbrs.begin(); }
229 const_iterator begin() const { return mbrs.begin(); }
230 iterator end() { return mbrs.end(); }
231 const_iterator end() const { return mbrs.end(); }
232
233 void serialize(std::ostream *out) const;
234 void deserialize(std::istream *in);
235
236 private:
237 RandAccessUIntSet mbrs{};
238 };
239
240 class GroupMgr : public GroupSelectionIface {
241 public:
242 void add_member_to_group(grp_hdl_t grp, mbr_hdl_t mbr) override;
243 void remove_member_from_group(grp_hdl_t grp, mbr_hdl_t mbr) override;
244
245 mbr_hdl_t get_from_hash(grp_hdl_t grp, hash_t h) const override;
246
247 void reset() override;
248
249 void insert_group(grp_hdl_t grp);
250
251 size_t group_size(grp_hdl_t grp) const;
252
253 GroupInfo &at(grp_hdl_t grp);
254 const GroupInfo &at(grp_hdl_t grp) const;
255
256 void clear();
257
258 private:
259 std::vector<GroupInfo> groups{};
260 };
261
262 private:
263 mbr_hdl_t choose_from_group(grp_hdl_t grp, const Packet &pkt) const;
264
265 MatchErrorCode get_member_(mbr_hdl_t handle, Member *member) const;
266
267 MatchErrorCode get_group_(grp_hdl_t grp, Group *group) const;
268
269 void entries_insert(mbr_hdl_t mbr, ActionEntry &&entry);
270
271 // lock can be acquired by MatchTableIndirect
272 ReadLock lock_read() const { return ReadLock(t_mutex); }
273 WriteLock lock_write() const { return WriteLock(t_mutex); }
274
275 // this method is called by MatchTableIndirect and assumes that the provided
276 // index is correct
277 void dump_entry(std::ostream *out, const IndirectIndex &index) const;
278
279 // called by MatchTableIndirect for reference counting (a member cannot be
280 // deleted if match entries are pointing to it)
281 void ref_count_increase(const IndirectIndex &index);
282 void ref_count_decrease(const IndirectIndex &index);
283
284 bool is_valid_mbr(mbr_hdl_t mbr) const {
285 return mbr_handles.valid_handle(mbr);
286 }
287
288 bool is_valid_grp(grp_hdl_t grp) const {
289 return grp_handles.valid_handle(grp);
290 }
291
292 bool group_is_empty(grp_hdl_t grp) const;
293
294 const ActionEntry &lookup(const Packet &pkt,
295 const IndirectIndex &index) const;
296
297 private:
298 mutable boost::shared_mutex t_mutex{};
299 bool with_selection;
300 std::vector<ActionEntry> action_entries{};
301 IndirectIndexRefCount index_ref_count{};
302 HandleMgr mbr_handles{};
303 HandleMgr grp_handles{};
304 size_t num_members{0};
305 size_t num_groups{0};
306 GroupMgr grp_mgr{};
307 std::shared_ptr<GroupSelectionIface> grp_selector_{nullptr};
308 GroupSelectionIface *grp_selector{&grp_mgr};
309 std::unique_ptr<Calculation> hash{nullptr};
310};
311
312} // namespace bm
313
314#endif // BM_BM_SIM_ACTION_PROFILE_H_