mirror of
https://gitlab.com/prpl-foundation/prplmesh/prplMesh.git
synced 2025-12-20 01:21:22 +08:00
TS: integrate 8021q subifaces impl into ApAutoConfigurationTask
Remove old Traffic Separation implementation. Integrate new 8021q subifaces approach. Features: - apply TS on MultiAP-Policy msg from Controller - apply TS on boot if Enabled in custom agent DM Previous use-cases for TS are kept (like it was for old impl). Closes PPM-3472 Signed-off-by: Volodymyr Pavlenko <pavlenko.vv@pm.me>
This commit is contained in:
@@ -21,7 +21,6 @@ static std::shared_ptr<beerocks::nbapi::Amxrt> guarantee = nullptr;
|
||||
#include "backhaul_manager/backhaul_manager.h"
|
||||
#include "platform_manager/platform_manager.h"
|
||||
#include "son_slave_thread.h"
|
||||
#include "traffic_separation.h"
|
||||
|
||||
#include <bcl/beerocks_cmdu_server_factory.h>
|
||||
#include <bcl/beerocks_config_file.h>
|
||||
@@ -398,7 +397,7 @@ static int run_beerocks_slave(beerocks::config_file::sConfigSlave &beerocks_slav
|
||||
beerocks::bpl::set_ambiorix_impl_ptr(amb_dm_obj);
|
||||
|
||||
{
|
||||
auto db = beerocks::AgentDB::get();
|
||||
auto db = beerocks::AgentDB::get();
|
||||
|
||||
// Load and set traffic separation profile_x_disallow_override (See beerocks_agent.conf)
|
||||
auto profile = beerocks::string_utils::stoi(
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
|
||||
#include "gate/1905_beacon_query_to_vs.h"
|
||||
#include "gate/vs_beacon_response_to_1905.h"
|
||||
#include "traffic_separation.h"
|
||||
|
||||
// BPL Error Codes
|
||||
#include <bpl/bpl_cfg.h>
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
#include "ap_autoconfiguration_task.h"
|
||||
#include "link_metrics_collection_task.h"
|
||||
#include "traffic_separation_task.h"
|
||||
|
||||
#include "../agent_db.h"
|
||||
#include "../son_slave_thread.h"
|
||||
#include "../tlvf_utils.h"
|
||||
#include "../traffic_separation.h"
|
||||
#include "multi_vendor.h"
|
||||
#include <bcl/beerocks_config_file.h>
|
||||
|
||||
@@ -108,6 +108,7 @@ bool is_valid_op_std(const std::string &radio_iface,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static constexpr uint8_t AUTOCONFIG_DISCOVERY_TIMEOUT_SECONDS = 3;
|
||||
@@ -287,25 +288,6 @@ void ApAutoConfigurationTask::handle_event(uint8_t event_enum_value, const void
|
||||
|
||||
db->statuses.ap_autoconfiguration_completed = false;
|
||||
|
||||
if (!m_traffic_separation_configurator) {
|
||||
m_traffic_separation_configurator = std::make_unique<TrafficSeparation>();
|
||||
}
|
||||
|
||||
// Reset the traffic separation configuration as they will be reconfigured on
|
||||
// autoconfiguration.
|
||||
m_traffic_separation_configurator->clear_configuration();
|
||||
|
||||
// Remove the Primary Vlan configuration in Transport process
|
||||
if (!m_btl_ctx.m_broker_client->configure_primary_vlan_id(0, false)) {
|
||||
LOG(ERROR) << "Failed configuring transport process!";
|
||||
}
|
||||
|
||||
// Reset the transport monitoring on bridge interfaces
|
||||
if (!m_btl_ctx.m_broker_client->configure_interfaces(db->bridge.iface_name, {}, true,
|
||||
true)) {
|
||||
LOG(ERROR) << "Failed configuring transport process!";
|
||||
}
|
||||
|
||||
// Reset the discovery statuses.
|
||||
for (auto &discovery_status : m_discovery_status) {
|
||||
discovery_status.second = {};
|
||||
@@ -364,18 +346,9 @@ void ApAutoConfigurationTask::handle_event(uint8_t event_enum_value, const void
|
||||
break;
|
||||
}
|
||||
case APPLY_CONFIG_FOR_NEW_IFACE: {
|
||||
auto db = AgentDB::get();
|
||||
for (const auto radio : db->get_radios_list()) {
|
||||
if (!radio) {
|
||||
continue;
|
||||
}
|
||||
for (auto &bss : radio->front.bssids) {
|
||||
if (bss.backhaul_bss) {
|
||||
m_traffic_separation_configurator->apply_policy_for_new_interface(
|
||||
bss.iface_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(DEBUG) << "Trigger traffic separation on APPLY_CONFIG_FOR_NEW_IFACE";
|
||||
m_btl_ctx.task_pool_send_event(eTaskType::TRAFFIC_SEPARATION,
|
||||
TrafficSeparationTask::eEvent::TS_NEW_BH_STA_IFACE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -560,7 +533,10 @@ void ApAutoConfigurationTask::configuration_complete_wait_action(const std::stri
|
||||
FSM_MOVE_STATE(radio_iface, eState::CONFIGURED);
|
||||
|
||||
LOG(TRACE) << "Finished configuration on " << radio_iface;
|
||||
m_traffic_separation_configurator->apply_policy(radio_iface);
|
||||
|
||||
LOG(DEBUG) << "Trigger traffic separation on ApAutoConfigurationTask eState::CONFIGURED";
|
||||
m_btl_ctx.task_pool_send_event(eTaskType::TRAFFIC_SEPARATION,
|
||||
TrafficSeparationTask::eEvent::TS_NEW_BH_STA_IFACE);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1638,19 +1614,13 @@ void ApAutoConfigurationTask::handle_multi_ap_policy_config_request(
|
||||
}
|
||||
|
||||
for (const auto &radios_conf_param_kv : m_radios_conf_params) {
|
||||
const auto &radio_iface = radios_conf_param_kv.first;
|
||||
const auto &conf_params = radios_conf_param_kv.second;
|
||||
|
||||
if (conf_params.state == eState::CONFIGURED) {
|
||||
// Configure the Primary VLAN in Transport Process
|
||||
if (!m_btl_ctx.m_broker_client->configure_primary_vlan_id(
|
||||
db->traffic_separation.primary_vlan_id, true)) {
|
||||
LOG(ERROR) << "Failed configuring transport process!";
|
||||
}
|
||||
m_traffic_separation_configurator->apply_policy(radio_iface);
|
||||
} else {
|
||||
LOG(WARNING) << "autoconfiguration procedure is not completed yet, traffic separation "
|
||||
<< "policy cannot be applied";
|
||||
// Trigger TrafficSeparationTask on Multi-AP Policy Request received
|
||||
LOG(DEBUG) << "Trigger traffic separation on Multi-AP Policy Request";
|
||||
m_btl_ctx.task_pool_send_event(eTaskType::TRAFFIC_SEPARATION,
|
||||
TrafficSeparationTask::eEvent::TS_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2536,7 +2506,9 @@ void ApAutoConfigurationTask::handle_vs_vaps_list_update_notification(
|
||||
void ApAutoConfigurationTask::handle_vs_apply_vlan_policy_request(
|
||||
ieee1905_1::CmduMessageRx &cmdu_rx, int fd, std::shared_ptr<beerocks_header> beerocks_header)
|
||||
{
|
||||
m_traffic_separation_configurator->apply_policy();
|
||||
LOG(TRACE) << "ApAutoConfigurationTask::handle_vs_apply_vlan_policy_request";
|
||||
m_btl_ctx.task_pool_send_event(eTaskType::TRAFFIC_SEPARATION,
|
||||
TrafficSeparationTask::eEvent::TS_ENABLE);
|
||||
}
|
||||
|
||||
bool ApAutoConfigurationTask::
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#ifndef _AP_AUTOCONFIGURATION_TASK_H_
|
||||
#define _AP_AUTOCONFIGURATION_TASK_H_
|
||||
|
||||
#include "../traffic_separation.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <mapf/common/encryption.h>
|
||||
@@ -147,8 +146,6 @@ private:
|
||||
// template argument.
|
||||
std::unordered_map<eFreqType, sDiscoveryStatus, std::hash<int>> m_discovery_status;
|
||||
|
||||
std::unique_ptr<net::TrafficSeparation> m_traffic_separation_configurator;
|
||||
|
||||
bool m_task_is_active = false;
|
||||
|
||||
slave_thread &m_btl_ctx;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "../helpers/link_metrics/ieee802_3_link_metrics_collector.h"
|
||||
#include "../helpers/media_type.h"
|
||||
#include "../son_slave_thread.h"
|
||||
#include "../traffic_separation.h"
|
||||
#include "multi_vendor.h"
|
||||
|
||||
#include <beerocks/tlvf/beerocks_message_apmanager.h>
|
||||
|
||||
@@ -1,343 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2016-2020 the prplMesh contributors (see AUTHORS.md)
|
||||
*
|
||||
* This code is subject to the terms of the BSD+Patent license.
|
||||
* See LICENSE file for more details.
|
||||
*/
|
||||
#include <bcl/beerocks_event_loop_impl.h>
|
||||
#include <bcl/beerocks_utils.h>
|
||||
#include <bcl/network/network_utils.h>
|
||||
#include <btl/broker_client_factory_factory.h>
|
||||
|
||||
#include "agent_db.h"
|
||||
#include "traffic_separation.h"
|
||||
|
||||
constexpr char DOT_PVID_SUFFIX[] = ".pvid";
|
||||
#define PVID_SUFFIX &DOT_PVID_SUFFIX[1]
|
||||
namespace beerocks {
|
||||
namespace net {
|
||||
|
||||
TrafficSeparation::TrafficSeparation() {}
|
||||
|
||||
void TrafficSeparation::clear_configuration()
|
||||
{
|
||||
LOG(DEBUG) << "Clearing traffic separation policy!";
|
||||
|
||||
auto db = AgentDB::get();
|
||||
|
||||
for (auto &radio : db->get_radios_list()) {
|
||||
for (uint8_t bss_id = 0; bss_id < radio->front.bssids.size(); bss_id++) {
|
||||
auto &bss = radio->front.bssids[bss_id];
|
||||
auto &ssid_map = db->traffic_separation.ssid_vid_mapping;
|
||||
auto found_it = ssid_map.find(bss.ssid);
|
||||
if (found_it == ssid_map.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// consider vap_id shift when main vap_id is greater than 0
|
||||
// (case of glinet where main vap is wlan0-1)
|
||||
auto iface_ids = utils::get_ids_from_iface_string(radio->front.iface_name);
|
||||
if (iface_ids.vap_id >= IFACE_VAP_ID_MIN) {
|
||||
bss_id += iface_ids.vap_id;
|
||||
}
|
||||
|
||||
// TODO: Save the bss iface name on the database instead of using bss ID.
|
||||
auto bss_iface_name =
|
||||
utils::get_iface_string_from_iface_vap_ids(radio->front.iface_name, bss_id);
|
||||
auto vid = found_it->second;
|
||||
|
||||
// Remove VLAN packet filter.
|
||||
network_utils::set_vlan_packet_filter(false, bss_iface_name, vid);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto ð_port : db->ethernet.lan) {
|
||||
network_utils::set_vlan_packet_filter(false, eth_port.iface_name);
|
||||
}
|
||||
network_utils::set_vlan_packet_filter(false, db->ethernet.wan.iface_name);
|
||||
|
||||
db->traffic_separation.primary_vlan_id = 0;
|
||||
db->traffic_separation.secondary_vlans_ids.clear();
|
||||
db->traffic_separation.ssid_vid_mapping.clear();
|
||||
network_utils::set_vlan_filtering(db->bridge.iface_name, 0);
|
||||
}
|
||||
|
||||
void TrafficSeparation::apply_policy(const std::string &radio_iface)
|
||||
{
|
||||
// Since the following call is locking the database, thread safety is promised on this function.
|
||||
auto db = AgentDB::get();
|
||||
|
||||
network_utils::set_vlan_filtering(db->bridge.iface_name,
|
||||
db->traffic_separation.primary_vlan_id);
|
||||
|
||||
// If the primary VID has changed to zero, vlan filtering is disabled, so there is no point
|
||||
// modifying the VLAN policy on the platform interfaces.
|
||||
if (db->traffic_separation.primary_vlan_id == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Apply traffic separation policy";
|
||||
|
||||
// The Bridge, the WAN ports and the LAN ports should all have "Tagged Port" policy.
|
||||
// Update the Bridge Policy
|
||||
bool is_bridge = true;
|
||||
set_vlan_policy(db->bridge.iface_name, ePortMode::TAGGED_PORT_PRIMARY_UNTAGGED, is_bridge);
|
||||
|
||||
// Since we already set the bridge, and there are no more bridge interfaces, the 'bridge_iface'
|
||||
// is set to 'false' from now on.
|
||||
is_bridge = false;
|
||||
|
||||
// Update WAN and LAN Ports.
|
||||
if (!db->device_conf.local_gw && !db->ethernet.wan.iface_name.empty()) {
|
||||
set_vlan_policy(db->ethernet.wan.iface_name, ePortMode::TAGGED_PORT_PRIMARY_UNTAGGED,
|
||||
is_bridge);
|
||||
}
|
||||
for (const auto &lan_iface_info : db->ethernet.lan) {
|
||||
set_vlan_policy(lan_iface_info.iface_name, ePortMode::TAGGED_PORT_PRIMARY_UNTAGGED,
|
||||
is_bridge);
|
||||
}
|
||||
|
||||
// Wireless Backhaul
|
||||
if (!db->device_conf.local_gw && !db->backhaul.selected_iface_name.empty() &&
|
||||
db->backhaul.connection_type == AgentDB::sBackhaul::eConnectionType::Wireless) {
|
||||
|
||||
auto radio = db->radio(db->backhaul.selected_iface_name);
|
||||
if (!radio) {
|
||||
LOG(ERROR) << "Could not find Backhaul Radio interface!";
|
||||
return;
|
||||
}
|
||||
|
||||
// Effective Multi-AP Profile = minimum of local capability, and bBSS
|
||||
// (upstream AP) profile. This ensures the link never advertises or enables
|
||||
// features (TS, SP, R3/4) that are unsupported by any participant in the path.
|
||||
auto profile_min = std::min({int(db->backhaul.backhaul_bss_multi_ap_profile),
|
||||
int(db->device_conf.multi_ap_profile)});
|
||||
LOG(INFO) << "TS decision: local =" << int(db->device_conf.multi_ap_profile)
|
||||
<< " peer =" << db->backhaul.backhaul_bss_multi_ap_profile
|
||||
<< " -> effective=" << profile_min;
|
||||
|
||||
if (profile_min > wfa_map::tlvProfile2MultiApProfile::eMultiApProfile::MULTIAP_PROFILE_1) {
|
||||
set_vlan_policy(radio->back.iface_name, ePortMode::TAGGED_PORT_PRIMARY_TAGGED,
|
||||
is_bridge);
|
||||
} else {
|
||||
set_vlan_policy(radio->back.iface_name, ePortMode::UNTAGGED_PORT, is_bridge,
|
||||
db->traffic_separation.primary_vlan_id);
|
||||
}
|
||||
}
|
||||
|
||||
// If radio interface has not been given, then stop configuring the VLAN policy after finished
|
||||
// to configure the bridge, ethernet ports and wireless backhaul interface.
|
||||
// This should happen whenever the backhaul connects, and we need to update the Primary VLAN
|
||||
// of the platform so we would be able to get messages from the Controller.
|
||||
if (radio_iface.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Policy given Radio interface.
|
||||
auto radio = db->radio(radio_iface);
|
||||
if (!radio) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &bss : radio->front.bssids) {
|
||||
// Skip unconfigured BSS.
|
||||
if (bss.ssid.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "BSS " << bss.mac << ", ssid:" << bss.ssid << ", fBSS: " << bss.fronthaul_bss
|
||||
<< ", bBSS: " << bss.backhaul_bss
|
||||
<< ", p1_dis: " << bss.backhaul_bss_disallow_profile1_agent_association
|
||||
<< ", p2_dis: " << bss.backhaul_bss_disallow_profile2_agent_association;
|
||||
|
||||
std::string bss_iface;
|
||||
|
||||
if (!network_utils::linux_iface_get_name(bss.mac, bss_iface)) {
|
||||
LOG(WARNING) << "Interface with MAC " << bss.mac << " does not exist";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fronthaul-only BSS: set untagged VID based on SSID->VID mapping.
|
||||
if (bss.fronthaul_bss && !bss.backhaul_bss) {
|
||||
auto it = db->traffic_separation.ssid_vid_mapping.find(bss.ssid);
|
||||
if (it == db->traffic_separation.ssid_vid_mapping.end()) {
|
||||
LOG(INFO) << "SSID '" << bss.ssid << "' not found in SSID->VID map, skip.";
|
||||
continue;
|
||||
}
|
||||
set_vlan_policy(bss_iface, ePortMode::UNTAGGED_PORT, is_bridge, it->second);
|
||||
}
|
||||
// Backhaul-only BSS.
|
||||
else if (!bss.fronthaul_bss && bss.backhaul_bss) {
|
||||
if (bss.backhaul_bss_disallow_profile1_agent_association ==
|
||||
bss.backhaul_bss_disallow_profile2_agent_association) {
|
||||
LOG(WARNING) << "bBSS invalid configuration - "
|
||||
<< "profile1_disallow == profile2_disallow == "
|
||||
<< bss.backhaul_bss_disallow_profile1_agent_association;
|
||||
|
||||
if (db->device_conf.unsupported_profile_disallow_policy ==
|
||||
eUnsupportedProfileDisallowPolicy::NO_OVERRIDE) {
|
||||
continue;
|
||||
}
|
||||
LOG(DEBUG) << "profile_x_disallow_override is set on profile "
|
||||
<< db->device_conf.unsupported_profile_disallow_policy;
|
||||
|
||||
//Overriding bBSS profile disallow configuration if db->device_conf.unsupported_profile_disallow_policy not NO_OVERRIDE
|
||||
bss.backhaul_bss_disallow_profile1_agent_association =
|
||||
(db->device_conf.unsupported_profile_disallow_policy ==
|
||||
eUnsupportedProfileDisallowPolicy::FORCE_PROFILE2);
|
||||
bss.backhaul_bss_disallow_profile2_agent_association =
|
||||
(db->device_conf.unsupported_profile_disallow_policy ==
|
||||
eUnsupportedProfileDisallowPolicy::FORCE_PROFILE1);
|
||||
}
|
||||
auto bss_iface_netdevs =
|
||||
network_utils::get_bss_ifaces(bss_iface, db->bridge.iface_name);
|
||||
|
||||
for (const auto &iface_name : bss_iface_netdevs) {
|
||||
// Profile-2 backhaul BSS -> tagged primary + tagged secondary.
|
||||
if (bss.backhaul_bss_disallow_profile1_agent_association ||
|
||||
db->device_conf.unsupported_profile_disallow_policy ==
|
||||
eUnsupportedProfileDisallowPolicy::FORCE_PROFILE2) {
|
||||
set_vlan_policy(iface_name, ePortMode::TAGGED_PORT_PRIMARY_TAGGED, is_bridge);
|
||||
}
|
||||
// Profile-1 backhaul BSS -> untagged primary VID.
|
||||
else {
|
||||
set_vlan_policy(iface_name, ePortMode::UNTAGGED_PORT, is_bridge,
|
||||
db->traffic_separation.primary_vlan_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Combined fBSS & bBSS - Currently Support only Profile-1 (PPM-1418)
|
||||
else {
|
||||
if (!bss.backhaul_bss_disallow_profile2_agent_association) {
|
||||
|
||||
// Note: If Combined mode with profile 2 will be supported, need to create a VLAN
|
||||
// interface for it to support tagging on multicast messages.
|
||||
LOG(WARNING) << "bBSS invalid configuration! "
|
||||
<< "Combined BSS not supported with Profile-2 bBSS - Skip";
|
||||
continue;
|
||||
}
|
||||
if (bss.backhaul_bss_disallow_profile1_agent_association) {
|
||||
LOG(ERROR) << "bBSS invalid configuration! "
|
||||
<< "Profile-1 and Profile-2 Backhaul connection are both disallowed - "
|
||||
"Skip";
|
||||
continue;
|
||||
}
|
||||
|
||||
set_vlan_policy(bss_iface, ePortMode::UNTAGGED_PORT, is_bridge,
|
||||
db->traffic_separation.primary_vlan_id);
|
||||
|
||||
auto bss_iface_netdevs =
|
||||
network_utils::get_bss_ifaces(bss_iface, db->bridge.iface_name);
|
||||
|
||||
for (const auto &iface_name : bss_iface_netdevs) {
|
||||
set_vlan_policy(iface_name, ePortMode::UNTAGGED_PORT, is_bridge,
|
||||
db->traffic_separation.primary_vlan_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// - No DHCP/IP configuration here. Main and guest networks br-lan and br-guest are handled by prplos
|
||||
// - No creation of bridge subinterfaces (e.g., br-lan.20).
|
||||
}
|
||||
|
||||
void TrafficSeparation::apply_policy_for_new_interface(const std::string &bss_iface)
|
||||
{
|
||||
auto db = AgentDB::get();
|
||||
bool is_bridge = false;
|
||||
|
||||
// If the primary VID has changed to zero, vlan filtering is disabled, so there is no point
|
||||
// modifying the VLAN policy on the platform interfaces.
|
||||
if (db->traffic_separation.primary_vlan_id == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto bss_iface_netdevs = network_utils::get_bss_ifaces(bss_iface, db->bridge.iface_name);
|
||||
|
||||
for (const auto &bss_iface_netdev : bss_iface_netdevs) {
|
||||
// Apply rules only to the new interface
|
||||
if (bss_iface_netdev == bss_iface) {
|
||||
continue;
|
||||
}
|
||||
if (!beerocks::net::network_utils::linux_add_iface_to_bridge(db->bridge.iface_name,
|
||||
bss_iface_netdev)) {
|
||||
LOG(INFO) << "The wireless interface " << bss_iface_netdev
|
||||
<< " is already in the bridge";
|
||||
}
|
||||
// Profile-2 Backhaul BSS
|
||||
if (db->device_conf.unsupported_profile_disallow_policy ==
|
||||
eUnsupportedProfileDisallowPolicy::FORCE_PROFILE2) {
|
||||
set_vlan_policy(bss_iface_netdev, ePortMode::TAGGED_PORT_PRIMARY_TAGGED, is_bridge);
|
||||
}
|
||||
// Profile-1 Backhaul BSS
|
||||
else {
|
||||
set_vlan_policy(bss_iface_netdev, ePortMode::UNTAGGED_PORT, is_bridge,
|
||||
db->traffic_separation.primary_vlan_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrafficSeparation::set_vlan_policy(const std::string &iface, ePortMode port_mode,
|
||||
bool is_bridge, uint16_t untagged_port_vid)
|
||||
{
|
||||
if (iface.empty()) {
|
||||
LOG(ERROR) << "iface is empty!";
|
||||
return;
|
||||
}
|
||||
|
||||
// Helper variables to make the code more readable.
|
||||
bool del = true; // First, remove all VIDs (vid=0).
|
||||
bool pvid;
|
||||
bool untagged;
|
||||
|
||||
network_utils::set_iface_vid_policy(iface, del, 0, is_bridge);
|
||||
|
||||
del = false;
|
||||
|
||||
if (port_mode == ePortMode::TAGGED_PORT_PRIMARY_UNTAGGED ||
|
||||
port_mode == ePortMode::TAGGED_PORT_PRIMARY_TAGGED) {
|
||||
if (port_mode == ePortMode::TAGGED_PORT_PRIMARY_UNTAGGED) {
|
||||
// Set the new Primary VLAN with "PVID" and "Egress Untagged" policy.
|
||||
pvid = true;
|
||||
untagged = true;
|
||||
} else {
|
||||
// Set the new Primary VLAN as Not "PVID" and Not "Egress Untagged" policy.
|
||||
pvid = false;
|
||||
untagged = false;
|
||||
}
|
||||
auto db = AgentDB::get();
|
||||
network_utils::set_iface_vid_policy(iface, del, db->traffic_separation.primary_vlan_id,
|
||||
is_bridge, pvid, untagged);
|
||||
|
||||
// Add secondary VIDs.
|
||||
pvid = false;
|
||||
untagged = false;
|
||||
for (const auto sec_vid : db->traffic_separation.secondary_vlans_ids) {
|
||||
network_utils::set_iface_vid_policy(iface, del, sec_vid, is_bridge, pvid, untagged);
|
||||
}
|
||||
|
||||
// Double tagged packets with S-Tag must be filtered on tagged ports.
|
||||
if (!is_bridge) {
|
||||
network_utils::set_vlan_packet_filter(true, iface);
|
||||
}
|
||||
}
|
||||
// port_mode == UNTAGGED_PORT
|
||||
else {
|
||||
if (!untagged_port_vid) {
|
||||
LOG(ERROR) << "Untagged Port VID was not set on port_mode of UNTAGGED_PORT";
|
||||
return;
|
||||
}
|
||||
// Set the new Primary VLAN with "PVID" and "Egress Untagged" policy.
|
||||
pvid = true;
|
||||
untagged = true;
|
||||
is_bridge = false; // Untagged Port cannot be a bridge interface.
|
||||
network_utils::set_iface_vid_policy(iface, del, untagged_port_vid, is_bridge, pvid,
|
||||
untagged);
|
||||
|
||||
// Filter packets containing the VID of the Untagged Port.
|
||||
network_utils::set_vlan_packet_filter(true, iface, untagged_port_vid);
|
||||
}
|
||||
}
|
||||
} // namespace net
|
||||
} // namespace beerocks
|
||||
@@ -1,154 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2016-2020 the prplMesh contributors (see AUTHORS.md)
|
||||
*
|
||||
* This code is subject to the terms of the BSD+Patent license.
|
||||
* See LICENSE file for more details.
|
||||
*/
|
||||
|
||||
#ifndef _TRAFFIC_SEPARATION_H
|
||||
#define _TRAFFIC_SEPARATION_H
|
||||
|
||||
#include <bcl/network/net_struct.h>
|
||||
#include <btl/broker_client.h>
|
||||
|
||||
namespace beerocks {
|
||||
namespace net {
|
||||
|
||||
/*
|
||||
* When defining the bridge with "vlan_filtering", the bridge becomes VLAN aware.
|
||||
* If the bridge is VLAN aware, then it is possible to define VLAN policy to each bridged interface.
|
||||
* A single interface can support multiple VLAN policies, one for each VLAN ID allowed on that
|
||||
* interface.
|
||||
* Two VLAN policies that can be defined on an interface:
|
||||
* 1. "PVID" - Any untagged frames coming from the network (external to the switch)
|
||||
* will be assigned to the configured VLAN.
|
||||
* Only one VID can be defined as PVID, therefore, if changing the VLAN ID
|
||||
* with the PVID policy, it will remove the PVID policy of the previous
|
||||
* PVID VLAN automatically.
|
||||
*
|
||||
* 2. "Egress Untagged" - Any Egress frame sent to the network, will be stripped from the
|
||||
* configured VLAN tag.
|
||||
*
|
||||
* If a frame with a VLAN tag is entering an interface, but the interface is not assigned to the
|
||||
* VLAN ID of the frame, the frame will be dropped.
|
||||
*
|
||||
* An interface can be defined either as "Tagged Port" or "Untagged Port".
|
||||
* Tagged Port - A port is a "Tagged Port" when an interface is expecting frames containing VLAN
|
||||
* tags. An example of this is when two switches are connected and pass tagged
|
||||
* traffic. The sender will send a frame with a VLAN tag. The receiving switch will
|
||||
* see the VLAN tags, and if the VLAN is allowed, it will forward the frame as
|
||||
* required.
|
||||
*
|
||||
* Although a Tagged Port should receive tagged frames, it can also receive
|
||||
* untagged frames. When a Tagged Port receives untagged frames, it assumes they
|
||||
* belong to the Primary VLAN, so it will add the Primary VLAN ID to these frames.
|
||||
*
|
||||
* A tagged port shall be defined as "PVID, Untagged Egress" on the Primary VLAN of
|
||||
* the network and add all the secondary VLANs (Not "PVID" and not
|
||||
* "Egress Untagged").
|
||||
*
|
||||
* Untagged Port - An untagged port, connects to network clients. A network client is unaware of
|
||||
* any VLAN configuration. A connected client sends its traffic without any VLAN
|
||||
* tag on the frames.
|
||||
* When the frame reaches the Untagged port on a switch, the switch will add the
|
||||
* VLAN tag. The switch port is configured with a VLAN ID that it will put into the
|
||||
* tag.
|
||||
* When a frame leaves an untagged port, the switch strips the VLAN tag from the
|
||||
* frame.
|
||||
*
|
||||
* An Untagged Port shall be defined as "PVID, Untagged Egress" on as single VLAN
|
||||
* ID - The Primary VLAN or one of the Secondary VLANs.
|
||||
*/
|
||||
|
||||
class TrafficSeparation final {
|
||||
|
||||
public:
|
||||
explicit TrafficSeparation();
|
||||
|
||||
/**
|
||||
* @brief Apply traffic separation policy on the given radio interfaces, and all not
|
||||
* radio related interface (e.g bridge, LAN ports).
|
||||
*
|
||||
* @param radio_iface Radio interface to apply VLAN policy on. If not given, apply the policy
|
||||
* only on the bridge, ethernet ports and the wireless backhaul interface.
|
||||
*/
|
||||
void apply_policy(const std::string &radio_iface = {});
|
||||
|
||||
/**
|
||||
* @brief Apply traffic separation rules on the new interface that are created when a
|
||||
* newly onboarding agent associates with the BH VAP.
|
||||
*/
|
||||
void apply_policy_for_new_interface(const std::string &bss_iface);
|
||||
|
||||
/**
|
||||
* @brief Clear the traffic separation configuration from the Agent and the platform.
|
||||
*
|
||||
*/
|
||||
void clear_configuration();
|
||||
|
||||
private:
|
||||
enum class ePortMode {
|
||||
UNTAGGED_PORT,
|
||||
TAGGED_PORT_PRIMARY_UNTAGGED,
|
||||
TAGGED_PORT_PRIMARY_TAGGED
|
||||
};
|
||||
|
||||
struct sBridgeVlanInfo {
|
||||
explicit sBridgeVlanInfo(const std::string &iface_name_,
|
||||
const net::sIpv4Addr &subnet_ipv4_ = {},
|
||||
const std::string &subnetmask_ = std::string())
|
||||
: iface_name(iface_name_), subnet_ipv4(subnet_ipv4_), subnetmask(subnetmask_)
|
||||
{
|
||||
}
|
||||
std::string iface_name;
|
||||
net::sIpv4Addr subnet_ipv4;
|
||||
std::string subnetmask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set the VLAN policy on a given @a 'iface'.
|
||||
*
|
||||
* @param iface An interface to set the VLAN policy on.
|
||||
* @param port_mode Indicate what is the desired port policy.
|
||||
* @param is_bridge Should be set to true if the @a 'port_mode' is
|
||||
* @b 'TAGGED_PORT_PRIMARY_UNTAGGED' or @b 'TAGGED_PORT_PRIMARY_TAGGED' and the given @a 'iface'
|
||||
* is a bridge interface.
|
||||
* @param untagged_port_vid The interface VID when @a 'port_mode' is @b 'UNTAGGED_PORT'.
|
||||
*/
|
||||
void set_vlan_policy(const std::string &iface, ePortMode port_mode, bool is_bridge,
|
||||
uint16_t untagged_port_vid = 0);
|
||||
|
||||
/**
|
||||
* @brief Reconfigure DHCP server with list of interfaces.
|
||||
*
|
||||
* @details This function should be used only on the GW.
|
||||
*
|
||||
* @param vlans_of_bridge List of VLANs of the bridge information.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool reconf_dhcp(std::list<sBridgeVlanInfo> &vlans_of_bridge);
|
||||
|
||||
/**
|
||||
* @brief Send DHCP request on each VLAN of the bridge and assigning the responded IP to the
|
||||
* VLAN interface.
|
||||
*
|
||||
* @details This function should be used only on the Repeater.
|
||||
*
|
||||
* @param vlans_of_bridge List of VLANs of the bridge information.
|
||||
*/
|
||||
void assign_ip_to_vlan_iface(const std::list<sBridgeVlanInfo> &vlans_of_bridge);
|
||||
|
||||
/**
|
||||
* @brief Configure interface on the Transport.
|
||||
*
|
||||
* @param iface Interface to configure.
|
||||
* @param add true for adding interface, false to remove.
|
||||
* @param bridge Bridge name if the interface is inside a bridge, otherwise should be empty.
|
||||
*/
|
||||
void configure_transport(const std::string &iface, bool add, const std::string &bridge);
|
||||
};
|
||||
} // namespace net
|
||||
} // namespace beerocks
|
||||
|
||||
#endif
|
||||
@@ -29,7 +29,7 @@ class TrafficSeparationManager {
|
||||
public:
|
||||
TrafficSeparationManager() = default;
|
||||
virtual ~TrafficSeparationManager() { clear_policies(); }
|
||||
TrafficSeparationManager(const TrafficSeparationManager &) = delete;
|
||||
TrafficSeparationManager(const TrafficSeparationManager &) = delete;
|
||||
TrafficSeparationManager &operator=(const TrafficSeparationManager &) = delete;
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,7 +87,7 @@ inline bool is_untagged_mode(bool dis_p1, bool dis_p2, eUnsupportedProfileDisall
|
||||
if (valid_p2)
|
||||
return true;
|
||||
|
||||
return (policy == eUnsupportedProfileDisallowPolicy::FORCE_PROFILE2);
|
||||
return (policy == eUnsupportedProfileDisallowPolicy::FORCE_PROFILE1);
|
||||
}
|
||||
|
||||
} // namespace beerocks::net
|
||||
|
||||
Reference in New Issue
Block a user