blob: f0dd12bc41edd8fb808469ad410efe5e44743149 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PATCHPANEL_QOS_SERVICE_H_
#define PATCHPANEL_QOS_SERVICE_H_
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include <base/containers/flat_set.h>
#include <chromeos/net-base/dns_client.h>
#include "patchpanel/connmark_updater.h"
#include "patchpanel/conntrack_monitor.h"
#include "patchpanel/crostini_service.h"
#include "patchpanel/routing_service.h"
#include "patchpanel/shill_client.h"
namespace patchpanel {
class Datapath;
class SocketConnectionEvent;
// QoSService manages the network QoS feature (Quality of Service), which:
// - Automatically classifies traffic into QoS categories;
// - Allows other components to explicitly associate traffic with certain QoS
// categories;
// - Prioritizes traffic according to its QoS category (currently only for
// egress traffic on WiFi interfaces by leveraging WiFi QoS/WMM).
//
// In general, this class mainly interacts with iptables and conntrack for QoS
// management:
// - On starting, QoSService will install a group of iptables rules for traffic
// detection and DSCP marking. No jump rule will be added so these rules won't
// be active on this stage.
// - Jump rules may be added or removed on 1) QoS feature is enabled or disabled
// and 2) WiFi interface is added or removed.
// - Conntrack table is affected in two ways:
// - There are iptables rules to save/restore the QoS category bits between
// fwmark and connmark.
// - Conntrack table will be updated directly from this class on QoS-related
// socket connection events from other components. If the connmark update
// fails, a UDP connection will be added to pending list and try updating
// connmark again when it is notified to be established.
//
class QoSService {
public:
explicit QoSService(Datapath* datapath,
ConntrackMonitor* monitor,
ShillClient* shill_client);
// Provided for testing.
QoSService(Datapath* datapath,
ConntrackMonitor* monitor,
ShillClient* shill_client,
std::unique_ptr<net_base::DNSClientFactory> dns_client_factory);
~QoSService();
// QoSService is neither copyable nor movable.
QoSService(const QoSService&) = delete;
QoSService& operator=(const QoSService&) = delete;
// Enable or disable the QoS feature. Note that it will only affect new socket
// connections. The QoS treatment for the existing connections may or may not
// be changed.
void Enable();
void Disable();
bool is_enabled() const { return is_enabled_; }
// Listening to the shill Device change event for the per-interface setup.
// Currently this class only care about WiFi interfaces.
void OnPhysicalDeviceAdded(const ShillClient::Device& device);
void OnPhysicalDeviceRemoved(const ShillClient::Device& device);
void OnPhysicalDeviceDisconnected(const ShillClient::Device& device);
// Process socket connection events from ARC App monitor and modify connmark
// based on socket information.
void ProcessSocketConnectionEvent(
const patchpanel::SocketConnectionEvent& msg);
// Update iptables rules (done by Datapath) for DoH.
void OnDoHProvidersChanged();
void OnIPConfigChanged(const ShillClient::Device& shill_device);
// Listening to Borealis VM start and stop event for application of QoS marks.
void OnBorealisVMStarted(const std::string_view ifname);
void OnBorealisVMStopped(const std::string_view ifname);
// Set ConnmarkUpdater, only used for testing.
void SetConnmarkUpdaterForTesting(std::unique_ptr<ConnmarkUpdater> updater);
private:
// Resolves names of DoH providers and update iptables with the resolved
// result over |device|. The |device| should be connected, otherwise the name
// resolving will just fail.
void MaybeRefreshDoHRules(const ShillClient::Device& device);
// Dependencies.
Datapath* datapath_;
std::unique_ptr<net_base::DNSClientFactory> dns_client_factory_;
ConntrackMonitor* conntrack_monitor_;
ShillClient* shill_client_;
// QoS feature is disabled by default. This value can be changed in `Enable()`
// and `Disable()`.
bool is_enabled_ = false;
// Tracks the existing interfaces which this service cares about (currently
// only WiFi interfaces). This class doesn't care about whether the interface
// is connected (i.e., ready for routing) or not. We need to track this to
// support the case that QoS feature is enabled after the WiFi interface
// appeared.
base::flat_set<std::string> interfaces_;
// The DNS servers and the DoH providers used for the last update (the last
// update can be still ongoing or already finished).
std::vector<net_base::IPAddress> dns_servers_for_doh_;
ShillClient::DoHProviders doh_providers_;
// Defined in the qos_service.cc file. |doh_updator_| is responding for doing
// the async DNS queries and call the corresponding function in Datapath to
// update the iptables rules related to DoH. Reset in UpdateDoHProviders().
class DoHUpdater;
std::unique_ptr<DoHUpdater> doh_updater_;
// Manages connmark update requests for TCP and UDP connections.
std::unique_ptr<ConnmarkUpdater> connmark_updater_;
base::WeakPtrFactory<QoSService> weak_factory_{this};
};
} // namespace patchpanel
#endif // PATCHPANEL_QOS_SERVICE_H_