-
Notifications
You must be signed in to change notification settings - Fork 388
[WIP] Obtain all possible outputs generated by ActionSelector group members with single input packet #1316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Obtain all possible outputs generated by ActionSelector group members with single input packet #1316
Changes from 9 commits
338c086
fcee16a
b2340c8
bc09a68
ce3eaf5
1cee0dc
728705b
7229247
caa8675
8acdc93
b51b374
d996808
cf186d3
2b29b2c
4c83c81
d56bfb5
02d89d9
207569e
5b0c47f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /* Copyright 2013-present Contributors to the P4 Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| #ifndef BM_BM_SIM_REPLICATED_PKT_VEC_H_ | ||
| #define BM_BM_SIM_REPLICATED_PKT_VEC_H_ | ||
|
|
||
| #include "logger.h" | ||
| #include "packet.h" | ||
| #include "match_tables.h" | ||
| #include <vector> | ||
|
|
||
| namespace bm { | ||
| class MatchTableAbstract; | ||
| // TODO(Hao): should this be per ingress thread or just global? | ||
| class ReplicatedPktVec { | ||
| public: | ||
| ReplicatedPktVec(const ReplicatedPktVec&) = delete; | ||
| ReplicatedPktVec& operator=(const ReplicatedPktVec&) = delete; | ||
|
|
||
| static ReplicatedPktVec& instance() { | ||
| static ReplicatedPktVec instance_; | ||
| return instance_; | ||
| } | ||
|
|
||
| void set_next_nodes(const MatchTableAbstract *match_table, bool hit); | ||
| // TODO(Hao): deduplicate packets replciated | ||
|
|
||
| public: | ||
| // Replicated pkts will first be added to replicated_pkts | ||
| // in order to get the corresponding next table node. | ||
| // After the cont_node is set, the pkt will be added to replicated_pkts | ||
| std::vector<Packet *> replicated_pkts; | ||
| std::vector<std::pair<Packet *, p4object_id_t>> replicated_pkts_w_act_id; | ||
|
|
||
| private: | ||
| ReplicatedPktVec() = default; | ||
| }; | ||
|
|
||
| } // namespace bm | ||
|
|
||
| #endif // BM_BM_SIM_REPLICATED_PKT_VEC_H_ | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| #include <bm/bm_sim/P4Objects.h> | ||
| #include <bm/bm_sim/phv.h> | ||
| #include <bm/bm_sim/actions.h> | ||
| #include <bm/bm_sim/logger.h> | ||
|
|
||
| #include <iostream> | ||
| #include <istream> | ||
|
|
@@ -1655,8 +1656,20 @@ P4Objects::init_pipelines(const Json::Value &cfg_root, | |
| std::unique_ptr<ActionProfile> action_profile( | ||
| new ActionProfile(act_prof_name, act_prof_id, with_selection)); | ||
| if (with_selection) { | ||
| auto calc = process_cfg_selector(cfg_act_prof["selector"]); | ||
| action_profile->set_hash(std::move(calc)); | ||
| // TODO(Hao): clean debug logs | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove debug logs |
||
| BMLOG_DEBUG( | ||
| "Action profile '{}' with id {} has a selector", | ||
| act_prof_name, act_prof_id); | ||
|
|
||
| if(is_selector_fanout(cfg_act_prof["selector"])){ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Formatting: add space after "if" and before the ending "{" |
||
| BMLOG_DEBUG( | ||
| "Action profile '{}' with id {} enabled selector fanout", | ||
| act_prof_name, act_prof_id); | ||
| action_profile->set_selector_fanout(); | ||
| }else{ | ||
Hoooao marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| auto calc = process_cfg_selector(cfg_act_prof["selector"]); | ||
| action_profile->set_hash(std::move(calc)); | ||
| } | ||
|
Comment on lines
+1660
to
+1673
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this should really be a command-line option for a target, instead of a special "algorithm" in the JSON. It feels like running in this "mode" should not require updating the JSON. Unless maybe the goal is to target individual selectors, and not all of them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think ideally it would target individual selectors, though for our purposes I think it would be fine to only allow all-or-nothing for now if easier. That said, we felt the 'mode' was the best choice mostly because the other mode options are kinda non-sense in the presence of creating all outputs. E.g. what does it mean to hash a packet to a member when it should go to all of them? Or round-robin? So it seemed like it was just really a different selection scheme which is "Pick all". |
||
| } | ||
| add_action_profile(act_prof_name, std::move(action_profile)); | ||
| } | ||
|
|
@@ -2499,6 +2512,12 @@ P4Objects::check_hash(const std::string &name) const { | |
| return nullptr; | ||
| } | ||
|
|
||
| // TODO(Hao): messy, so i think use pragma is better | ||
| bool P4Objects::is_selector_fanout(const Json::Value &cfg_selector) const { | ||
| return cfg_selector.isMember("algo") && // not to hardcode names, fix later | ||
Hoooao marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| cfg_selector["algo"].asString() == "selector_fanout"; | ||
| } | ||
|
|
||
| std::unique_ptr<Calculation> | ||
| P4Objects::process_cfg_selector(const Json::Value &cfg_selector) const { | ||
| const auto selector_algo = cfg_selector["algo"].asString(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| #include <bm/bm_sim/action_profile.h> | ||
| #include <bm/bm_sim/logger.h> | ||
| #include <bm/bm_sim/packet.h> | ||
| #include <bm/bm_sim/replicated_pkt_vec.h> | ||
|
|
||
| #include <iostream> | ||
| #include <memory> | ||
|
|
@@ -126,6 +127,8 @@ ActionProfile::mbr_hdl_t | |
| ActionProfile::GroupMgr::get_from_hash(grp_hdl_t grp, hash_t h) const { | ||
| const auto &group_info = groups.at(grp); | ||
| auto s = group_info.size(); | ||
| BMLOG_DEBUG("Hao: Choosing member from group {} with hash {} (size {})", | ||
| grp, h, s); | ||
| return group_info.get_nth(h % s); | ||
| } | ||
|
|
||
|
|
@@ -175,9 +178,36 @@ ActionProfile::lookup(const Packet &pkt, const IndirectIndex &index) const { | |
| } else { | ||
| grp_hdl_t grp = index.get_grp(); | ||
| assert(is_valid_grp(grp)); | ||
| //Hao: critical part for fanout all possible members | ||
| std::vector<mbr_hdl_t> mbrs; | ||
| mbr = choose_from_group(grp, pkt); | ||
| // TODO(antonin): change to trace? | ||
| BMLOG_DEBUG_PKT(pkt, "Choosing member {} from group {}", mbr, grp); | ||
| BMLOG_DEBUG_PKT(pkt, "Chose member {} from group {}", mbr, grp); | ||
|
|
||
| if(selector_fanout_enabled){ | ||
| BMLOG_DEBUG_PKT(pkt, "Selector fanout enabled, choosing member from group {} WIP", grp); | ||
| mbrs = get_all_mbrs_from_group(grp); | ||
| for(auto m:mbrs){ | ||
| if(m == mbr){ | ||
| continue; | ||
|
||
| } | ||
| // TODO(Hao): apply_action in match_tables has a full procedure, | ||
| // need to make sure that directly applying the func does not | ||
| // cause any issues | ||
| //Things to consider: | ||
| // 1. set the entry index | ||
| // 2. set meters | ||
| // 3. set counters | ||
|
||
| // 4. incorporate with the debugger? | ||
| const ActionEntry &action = action_entries[m]; | ||
| Packet* rep_pkt = pkt.clone_with_phv_ptr().release(); | ||
| action.action_fn(rep_pkt); | ||
| BMLOG_DEBUG_PKT(*rep_pkt, "Action {} applied to replicated packet", | ||
| action); | ||
| ReplicatedPktVec::instance().replicated_pkts_w_act_id.emplace_back(rep_pkt, | ||
|
||
| action.action_fn.get_action_id()); | ||
| } | ||
| } | ||
| } | ||
| assert(is_valid_mbr(mbr)); | ||
|
|
||
|
|
@@ -617,4 +647,18 @@ ActionProfile::choose_from_group(grp_hdl_t grp, const Packet &pkt) const { | |
| return grp_selector->get_from_hash(grp, h); | ||
| } | ||
|
|
||
| std::vector<ActionProfile::mbr_hdl_t> | ||
| ActionProfile::get_all_mbrs_from_group(grp_hdl_t grp) const { | ||
| std::vector<ActionProfile::mbr_hdl_t> mbrs; | ||
| const GroupInfo& grp_info = grp_mgr.at(grp); | ||
| for(auto mbr = grp_info.begin(); mbr != grp_info.end(); ++mbr) { | ||
| mbrs.push_back(*mbr); | ||
| } | ||
|
||
| return mbrs; | ||
| } | ||
|
|
||
| void ActionProfile::set_selector_fanout(){ | ||
| selector_fanout_enabled = true; | ||
| } | ||
|
|
||
| } // namespace bm | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,11 +37,15 @@ Pipeline::apply(Packet *pkt) { | |
| BMLOG_DEBUG_PKT(*pkt, "Pipeline '{}': start", get_name()); | ||
| const ControlFlowNode *node = first_node; | ||
| while (node) { | ||
| BMLOG_DEBUG_PKT(*pkt, "Pipeline '{}': after applying node '{}'", | ||
| get_name(), node->get_name()); | ||
| if (pkt->is_marked_for_exit()) { | ||
| BMLOG_DEBUG_PKT(*pkt, "Packet is marked for exit, interrupting pipeline"); | ||
| break; | ||
| } | ||
| node = (*node)(pkt); | ||
| BMLOG_DEBUG_PKT(*pkt, "Pipeline '{}': before applying node '{}'", | ||
| get_name(), node ? node->get_name() : "None"); | ||
| } | ||
| BMELOG(pipeline_done, *pkt, *this); | ||
| DEBUGGER_NOTIFY_CTR( | ||
|
|
@@ -50,4 +54,35 @@ Pipeline::apply(Packet *pkt) { | |
| BMLOG_DEBUG_PKT(*pkt, "Pipeline '{}': end", get_name()); | ||
| } | ||
|
|
||
| // Hao: placeholder for path permutation, just seems easier to have another apply here | ||
| // Should snapshot some metadata/reg states before calling this | ||
| void Pipeline::apply_continued(Packet *pkt) { | ||
|
||
| const ControlFlowNode *cont_node = pkt->get_continue_node(); | ||
| // pipeline_start is used for monitoring and debugging purposes, we can have ours as well | ||
| // but should change this anyways to differentiate between the two applies | ||
| BMELOG(pipeline_start, *pkt, *this); | ||
| // TODO(antonin) | ||
| // this is temporary while we experiment with the debugger | ||
| DEBUGGER_NOTIFY_CTR( | ||
| Debugger::PacketId::make(pkt->get_packet_id(), pkt->get_copy_id()), | ||
| DBG_CTR_CONTROL | get_id()); | ||
| BMLOG_DEBUG_PKT(*pkt, "Pipeline '{}': continue from node '{}'", | ||
| get_name(), cont_node? cont_node->get_name() : "None"); | ||
| const ControlFlowNode *node = cont_node; | ||
| while (node) { | ||
| if (pkt->is_marked_for_exit()) { | ||
| BMLOG_DEBUG_PKT(*pkt, "Packet is marked for exit, interrupting pipeline"); | ||
| break; | ||
| } | ||
| node = (*node)(pkt); | ||
| } | ||
| // same | ||
| BMELOG(pipeline_done, *pkt, *this); | ||
| DEBUGGER_NOTIFY_CTR( | ||
| Debugger::PacketId::make(pkt->get_packet_id(), pkt->get_copy_id()), | ||
| DBG_CTR_EXIT(DBG_CTR_CONTROL) | get_id()); | ||
| pkt->reset_continue_node(); | ||
| BMLOG_DEBUG_PKT(*pkt, "Pipeline '{}': continue end", get_name()); | ||
| } | ||
|
|
||
| } // namespace bm | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't these be protected by a mutex?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently it is only used in ingress, which is single threaded, so it is safe. But added the mutex for egress later.