Source code for linuxnet.qos.actions.police

# Copyright (c) 2023, 2025, Panagiotis Tsirigotis

# This file is part of linuxnet-qos.
#
# linuxnet-qos is free software: you can redistribute it and/or
# modify it under the terms of version 3 of the GNU Affero General Public
# License as published by the Free Software Foundation.
#
# linuxnet-qos is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General
# Public License along with linuxnet-qos. If not, see
# <https://www.gnu.org/licenses/>.

"""
This module provides access to the ``police`` action.
"""

from typing import List, Optional

from ..deps import get_logger
from ..exceptions import TcParsingError
from ..parsers import TrafficFilterParser
from ..tcunit import bwstr2int, datastr2int

from .action import TrafficAction, ActionDecision

_logger = get_logger("linuxnet.qos.actions.police")


[docs]class PoliceAction(TrafficAction): """This class supports the **tc(8)** ``police`` action as documented in :manpage:`tc-police(8)`. """ KIND = 'police' def __init__(self, action_index: Optional[int] =None, *, rate: Optional[int] =None, burst: Optional[int] =None, mtu: Optional[int] =None, decision: ActionDecision, overhead: Optional[int] =None): """ :param action_index: an integer that effectively names the action :param rate: rate :param burst: burst :param mtu: MTU :param decision: control action to take :param overhead: overhead """ super().__init__(action_index, decision) self.__rate = rate self.__burst = burst self.__mtu = mtu self.__overhead = overhead
[docs] @classmethod def get_kind(cls) -> str: """Returns ``police`` """ return cls.KIND
[docs] def get_rate(self) -> Optional[int]: """Returns the rate """ return self.__rate
[docs] def get_burst(self) -> Optional[int]: """Returns the burst """ return self.__burst
[docs] def get_mtu(self) -> Optional[int]: """Returns the mtu """ return self.__mtu
[docs] def get_overhead(self) -> Optional[int]: """Returns the overhead """ return self.__overhead
def _action_specific_args(self) -> List[str]: """Returns a list of **tc(8)** arguments to create this action """ args = [] if self.__rate: args.extend(['rate', str(self.__rate)]) if self.__burst: args.extend(['burst', str(self.__burst)]) if self.__mtu: args.extend(['mtu', str(self.__mtu)]) if self.__overhead: args.extend(['overhead', str(self.__overhead)]) return args @classmethod def parse(cls, fields: List[str], _: 'LineGroupIterator') -> TrafficAction: """The ``fields`` list holds the line fields after ``police``. If the fields are successfully parsed, a :class:`PoliceAction` instance is returned. We expect all police-specific fields to be on the same line, so we do not make use of the line iterator. :meta private: """ # # The expected format of the fields is: # # 0x1 rate 256Kbit burst 10Kb mtu 2Kb action drop overhead 0b # # 0x1 is the action index. # fiter = iter(fields) action_index = int(next(fiter), 16) rate = None burst = None mtu = None decision = None overhead = None for field in fiter: if field == 'rate': rate = bwstr2int(next(fiter)) elif field == 'burst': burst = datastr2int(next(fiter)) elif field == 'mtu': mtu = datastr2int(next(fiter)) elif field == 'action': decision = ActionDecision.create_from_string(next(fiter)) elif field == 'overhead': overhead = datastr2int(next(fiter)) else: _logger.warning("unexpected police attribute: %s", field) if decision is None: raise TcParsingError("police control action missing") return PoliceAction( action_index, rate=rate, burst=burst, mtu=mtu, decision=decision, overhead=overhead)
TrafficFilterParser.register_action(action_name=PoliceAction.KIND, klass=PoliceAction)