From d0f40b144507573efbad6469c62d0c82b83c01b0 Mon Sep 17 00:00:00 2001 From: Volodymyr Samotiy Date: Thu, 21 Jul 2016 17:04:31 +0300 Subject: [PATCH] Add support for Black Hole Detection Change-Id: Ibb56674a453ede3661083838aaeef7bb2d1ae566 --- README.md | 51 + broadview_lib/bhd/__init__.py | 0 broadview_lib/bhd/agent_sampling_params.py | 56 + broadview_lib/bhd/bhd_parser.py | 1496 ++++++++++++++++++ broadview_lib/bhd/black_hole.py | 63 + broadview_lib/bhd/black_hole_event_report.py | 60 + broadview_lib/bhd/sflow_sampling_params.py | 88 ++ broadview_lib/bhd/sflow_sampling_status.py | 80 + broadview_lib/config/bhd.py | 533 +++++++ broadview_lib/tools/bv-bhdctl-examples.sh | 29 + broadview_lib/tools/bv-bhdctl.py | 379 +++++ broadview_lib/tools/bv-ctl-examples.sh | 22 + broadview_lib/tools/bv-ptctl-examples.sh | 39 + broadview_lib/tools/examples.sh | 22 +- 14 files changed, 2898 insertions(+), 20 deletions(-) create mode 100644 broadview_lib/bhd/__init__.py create mode 100644 broadview_lib/bhd/agent_sampling_params.py create mode 100644 broadview_lib/bhd/bhd_parser.py create mode 100644 broadview_lib/bhd/black_hole.py create mode 100644 broadview_lib/bhd/black_hole_event_report.py create mode 100644 broadview_lib/bhd/sflow_sampling_params.py create mode 100644 broadview_lib/bhd/sflow_sampling_status.py create mode 100644 broadview_lib/config/bhd.py create mode 100644 broadview_lib/tools/bv-bhdctl-examples.sh create mode 100644 broadview_lib/tools/bv-bhdctl.py create mode 100644 broadview_lib/tools/bv-ctl-examples.sh create mode 100644 broadview_lib/tools/bv-ptctl-examples.sh diff --git a/README.md b/README.md index ec28997..e5e251c 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,11 @@ A command line application that can be used to configure BroadView BST. A command line application that can be used to configure BroadView PacketTrace. +### bv-bhdctl.py + +A command line application that can be used to configure BroadView's Black +Hole Detection feature. + ### bv-ctl.py A command line application that can be used to issue general BroadView @@ -266,6 +271,52 @@ The class PTParser (found in pt/pt_parser.py) accepts the JSON payload that is sent by a BroadView agent for PacketTrace, and converts this payload into Python objects. It provides an API for accessing these objects. +## Black Hole Detection Configuration and Reports + +The bhd.py file in config contains various configuration and data gathering +classes. + +The following briefly summarizes these classes. For example usage, see the +unit test code in bhd.py, or the bv-bhdctl.py application. + +### BlackHoleDetectionEnable + +This class can be used to enable (or disable) black hole detection. + +### ConfigureBlackHole + +This class configures the Black Hole Detection functionality on the switch. + +### CancelBlackHole + +This class nullifies the configuration made by the ConfigureBlackHole class. + +### GetBlackHoleDetectionEnable + +This class can be used to determine of black hole detection is enabled or not. + +### GetBlackHole + +This class is used to get the current configuration of black hole detection +on the agent. + +### GetBlackHoleEventReport + +This class is used to get a black hole event report. It is only valid if the +agent sampling mode is configured on the agent. + +### GetSFlowSamplingStatus + +This class is used to get current sFlow sampling status of Black Holed +traffic. + +## BHDParser Object + +The class BHDParser (found in bhd/bhd_parser.py) accepts the JSON payload +that is sent by a BroadView agent for Black Hole Detection, and converts this +payload into Python objects. It provides an API for accessing the data that +is contained in these objects. + ## Unit tests To ensure that broadview-lib is decoupled from any (and all) OpenStack diff --git a/broadview_lib/bhd/__init__.py b/broadview_lib/bhd/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/broadview_lib/bhd/agent_sampling_params.py b/broadview_lib/bhd/agent_sampling_params.py new file mode 100644 index 0000000..7214eb7 --- /dev/null +++ b/broadview_lib/bhd/agent_sampling_params.py @@ -0,0 +1,56 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +class AgentSamplingParams(): + + def __init__(self): + self._waterMark = 0 + self._samplePeriodicity = 0 + self._sampleCount = 0 + + def getWaterMark(self): + return self._waterMark + + def getSamplePeriodicity(self): + return self._samplePeriodicity + + def getSampleCount(self): + return self._sampleCount + + def __repr__(self): + return "agent-sampling-params" + + def parse(self, data): + ret = True + + if "sampling-params" in data: + p = data["sampling-params"] + else: + ret = False + + if ret: + if "water-mark" in p: + self._waterMark = p["water-mark"] + else: + ret = False + if "sample-periodicity" in p: + self._samplePeriodicity = p["sample-periodicity"] + else: + ret = False + if "sample-count" in p: + self._sampleCount = p["sample-count"] + else: + ret = False + + return ret diff --git a/broadview_lib/bhd/bhd_parser.py b/broadview_lib/bhd/bhd_parser.py new file mode 100644 index 0000000..b95703e --- /dev/null +++ b/broadview_lib/bhd/bhd_parser.py @@ -0,0 +1,1496 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import black_hole_event_report +import sflow_sampling_status +import black_hole +import time +import unittest + +class ReportTypes: + BlackHole, BlackHoleEventReport, SFlowSamplingStatus = range(3) + +class BHDParser(): + def __init__(self): + self.__reportType = None + self.__black_hole = None + self.__black_hole_event_report = [] + self.__sflow_sampling_status = [] + + self.__reportHandlers = [self._handleBlackHole, + self._handleBlackHoleEventReport, + self._handleSFlowSamplingStatus] + + def getReportType(self): + return self.__reportType + + def getASICId(self): + return self.__asicId; + + def getTimestamp(self): + return self.__timestamp; + + def __repr__(self): + return "BHD" + + def dispatchReportParser(self, report): + ret = True + if report["realm"] in self.__handlers: + try: + self.__handlers[report["realm"]](report["data"]) + except: + ret = False + else: + ret = False + return ret + + def _handleBlackHoleEventReport(self, data): + ret = True + try: + report = data["report"] + except: + ret = False + report = None + if ret: + t = black_hole_event_report.BlackHoleEventReport() + ret = t.parse(report) + if ret: + self.__black_hole_event_report = t + + return ret + + def getBlackHoleEventReport(self): + return self.__black_hole_event_report + + def _handleSFlowSamplingStatus(self, data): + ret = True + try: + report = data["report"] + except: + ret = False + if ret: + t = sflow_sampling_status.SFlowSamplingStatus() + ret = t.parse(report) + if ret: + self.__sflow_sampling_status = t + + return ret + + def getSFlowSamplingStatus(self): + return self.__sflow_sampling_status + + def _handleBlackHole(self, data): + ret = True + try: + report = data["result"] + except: + report = [] + ret = False + + if ret: + t = black_hole.BlackHole() + ret = t.parse(report) + if ret: + self.__black_hole = t + + return ret + + def getBlackHole(self): + return self.__black_hole + + def process(self, data): + ret = True + if self.valid(data): + if data["method"] == "get-black-hole": + self.__reportType = ReportTypes.BlackHole + elif data["method"] == "get-black-hole-event-report": + self.__reportType = ReportTypes.BlackHoleEventReport + elif data["method"] == "get-sflow-sampling-status": + self.__reportType = ReportTypes.SFlowSamplingStatus + else: + ret = False + + if ret: + self.__asicId = data["asic-id"] + if "time-stamp" in data: + x = data["time-stamp"].strip() + try: + self.__timestamp = time.strptime(x, "%Y-%m-%d - %H:%M:%S") + except: + ret = False + + if ret: + if self.__reportType in range(len(self.__reportHandlers)): + ret = self.__reportHandlers[self.__reportType](data) + else: + ret = False + else: + ret = False + return ret + + def valid(self, data): + ret = True + keys = ["jsonrpc", "method", + "asic-id", "version", + "time-stamp"] + + if ret and "method" in data: + data["method"] = data["method"].strip() + if data["method"] != "get-black-hole" and \ + data["method"] != "get-black-hole-event-report" and \ + data["method"] != "get-sflow-sampling-status": + ret = False + else: + ret = False + + if ret: + for x in keys: + if not x in data: + if x == "time-stamp": + if data["method"] == "get-black-hole": + continue + ret = False + break + + if ret: + if not "report" in data and not "result" in data: + ret = False # must contain a result or report + + return ret + +class TestParser(unittest.TestCase): + + def setUp(self): + + self.get_black_hole_agent_1 = { + "jsonrpc": "2.0", + "asic-id": "1", + "method": "get-black-hole", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_missing_method = { + "jsonrpc": "2.0", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_invalid_method = { + "jsonrpc": "2.0", + "method": "get-black-hole-in-one", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_missing_asic = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_missing_result = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "id": 1 + } + + self.get_black_hole_agent_empty_result = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + }, + "id": 1 + } + + self.get_black_hole_agent_result_array = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": [ + ], + "id": 1 + } + + self.get_black_hole_agent_missing_port_list = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_missing_sampling_method = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_invalid_sampling_method = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "ice-cream", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_missing_sampling_params = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent" + }, + "id": 1 + } + + self.get_black_hole_agent_missing_water_mark = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_missing_sample_periodicity = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-count": 10 + } + }, + "id": 1 + } + + self.get_black_hole_agent_missing_sample_count = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + } + }, + "id": 1 + } + + self.get_black_hole_sflow_1 = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_method = { + "jsonrpc": "2.0", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_invalid_method = { + "jsonrpc": "2.0", + "method": "get-black-hole-abcd", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_asic = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_result = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "id": 1 + } + + self.get_black_hole_sflow_empty_result = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + }, + "id": 1 + } + + self.get_black_hole_sflow_result_array = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": [ + ], + "id": 1 + } + + self.get_black_hole_sflow_missing_sampling_method = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_invalid_sampling_method = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_sampling_params = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow", + "mirror-port": "10", + "sample-pool-size": 1 + }, + "id": 1 + } + + self.get_black_hole_sflow_invalid_sampling_method = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_encap_params = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_vlan_id = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_destination_ip = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_src_udp = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "destination-udp-port": 4321 + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_dst_udp = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + }, + "mirror-port": "10", + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_mirror_port = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "sample-pool-size": 1 + } + }, + "id": 1 + } + + self.get_black_hole_sflow_missing_sample_pool_size = { + "jsonrpc": "2.0", + "method": "get-black-hole", + "asic-id": "1", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "sflow-invalid", + "sampling-params": { + "encapsulation-params": { + "vlan-id": 1, + "destination-ip": "1.1.1.1", + "source-udp-port": 1234, + "destination-udp-port": 4321 + }, + "mirror-port": "10", + } + }, + "id": 1 + } + + self.get_black_hole_event_report_1 = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "ingress-port": "1", + "egress-port-list": ["2", "3"], + "black-holed-packet-count": 100, + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_missing_method = { + "jsonrpc": "2.0", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "ingress-port": "1", + "egress-port-list": ["2", "3"], + "black-holed-packet-count": 100, + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_invalid_method = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report-blah", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "ingress-port": "1", + "egress-port-list": ["2", "3"], + "black-holed-packet-count": 100, + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_missing_asic = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "ingress-port": "1", + "egress-port-list": ["2", "3"], + "black-holed-packet-count": 100, + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_missing_result = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + } + + self.get_black_hole_event_report_empty_result = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + } + } + + self.get_black_hole_event_report_result_array = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": [ + ] + } + + self.get_black_hole_event_report_missing_timestamp = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "report": { + "ingress-port": "1", + "egress-port-list": ["2", "3"], + "black-holed-packet-count": 100, + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_missing_ingress_port = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "egress-port-list": ["2", "3"], + "black-holed-packet-count": 100, + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_missing_egress_port_list = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "ingress-port": "1", + "black-holed-packet-count": 100, + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_missing_bhpc = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "ingress-port": "1", + "egress-port-list": ["2", "3"], + "sample-packet": "0010203232.." + } + } + + self.get_black_hole_event_report_missing_sample_packet = { + "jsonrpc": "2.0", + "method": "get-black-hole-event-report", + "asic-id": "1", + "version": "2", + "time-stamp": "2014-11-18 - 00:15:04 ", + "report": { + "ingress-port": "1", + "egress-port-list": ["2", "3"], + "black-holed-packet-count": 100, + } + } + + self.get_sflow_sampling_status_1 = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_method = { + "jsonrpc": "2.0", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_timestamp = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status-invalid", + "asic-id": "1", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_invalid_timestamp = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status-invalid", + "asic-id": "1", + "time-stamp": "invalid timestamp", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_invalid_method = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status-invalid", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_asic = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_data = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "time-stamp": "2014-11-18 - 00:15:04 ", + "asic-id": "1", + "version": "2", + "report": { + }, + "id": 1 + } + + self.get_sflow_sampling_status_data_object = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": {} + }, + "id": 1 + } + + self.get_sflow_sampling_status_data_string = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": "Hello World!" + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_result = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "id": 1 + } + + self.get_sflow_sampling_status_empty_result = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + }, + "id": 1 + } + + self.get_sflow_sampling_status_result_array = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": [ + ], + "id": 1 + } + + self.get_sflow_sampling_status_missing_port = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ + "sflow-sampling-enabled": 1, + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_sampling_enabled = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ "port": "2", + "sampled-packet-count": 100, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_sampled_packet_count = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + "black-holed-packet-count": 2000 + }] + }, + "id": 1 + } + + self.get_sflow_sampling_status_missing_black_holed_packet_count = { + "jsonrpc": "2.0", + "method": "get-sflow-sampling-status", + "asic-id": "1", + "time-stamp": "2014-11-18 - 00:15:04 ", + "version": "2", + "report": { + "data": [{ "port": "2", + "sflow-sampling-enabled": 1, + "black-holed-packet-count": 1000 + }, + { "port": "3", + "sflow-sampling-enabled": 1, + "sampled-packet-count": 200, + }] + }, + "id": 1 + } + + + self.get_black_hole_agent_1 = { + "jsonrpc": "2.0", + "asic-id": "1", + "method": "get-black-hole", + "version": "2", + "result": { + "port-list": ["1", "2", "3", "4"], + "sampling-method": "agent", + "sampling-params": { + "water-mark": 200, + "sample-periodicity": 15, + "sample-count": 10 + } + }, + "id": 1 + } + + def test_get_black_hole_agent_1(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_1) + self.assertEqual(ret, True) + rep = rep.getBlackHole() + self.assertTrue(rep != None) + self.assertEqual(rep.getSamplingMethod(), rep.AgentSampling) + portList = rep.getPortList() + self.assertTrue(len(portList), 4) + self.assertTrue("1" in portList) + self.assertTrue("2" in portList) + self.assertTrue("3" in portList) + self.assertTrue("4" in portList) + p = rep.getSamplingParams() + self.assertEqual(p.getWaterMark(), 200) + self.assertEqual(p.getSamplePeriodicity(), 15) + self.assertEqual(p.getSampleCount(), 10) + + def test_get_black_hole_agent_missing_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_method ) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_invalid_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_invalid_method) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_asic(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_asic) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_result(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_result) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_empty_result(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_empty_result) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_result_array(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_result_array) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_port_list(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_port_list) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_sampling_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_sampling_method) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_invalid_sampling_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_invalid_sampling_method) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_sampling_params(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_sampling_params) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_water_mark(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_water_mark) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_sample_periodicity(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_sample_periodicity) + self.assertEqual(ret, False) + + def test_get_black_hole_agent_missing_sample_count(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_agent_missing_sample_count) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_1(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_1) + self.assertEqual(ret, True) + rep = rep.getBlackHole() + self.assertTrue(rep != None) + self.assertEqual(rep.getSamplingMethod(), rep.SFlowSampling) + portList = rep.getPortList() + self.assertTrue(len(portList), 4) + self.assertTrue("1" in portList) + self.assertTrue("2" in portList) + self.assertTrue("3" in portList) + self.assertTrue("4" in portList) + p = rep.getSamplingParams() + self.assertEqual(p.getVLANId(), 1) + self.assertEqual(p.getDstIP(), "1.1.1.1") + self.assertEqual(p.getSrcUDPPort(), 1234) + self.assertEqual(p.getDstUDPPort(), 4321) + self.assertEqual(p.getMirrorPort(), "10") + self.assertEqual(p.getSamplePoolSize(), 1) + + def test_get_black_hole_sflow_missing_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_method) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_invalid_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_invalid_method) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_asic(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_asic) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_result(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_result) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_empty_result(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_empty_result) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_result_array(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_result_array) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_sampling_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_sampling_method) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_invalid_sampling_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_invalid_sampling_method) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_sampling_params(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_sampling_params) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_invalid_sampling_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_invalid_sampling_method) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_encap_params(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_encap_params) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_vlan_id(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_vlan_id) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_destination_ip(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_destination_ip) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_src_udp(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_src_udp) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_dst_udp(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_dst_udp) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_mirror_port(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_mirror_port) + self.assertEqual(ret, False) + + def test_get_black_hole_sflow_missing_sample_pool_size(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_sflow_missing_sample_pool_size) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_1(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_1) + self.assertEqual(ret, True) + rep = rep.getBlackHoleEventReport() + self.assertTrue(rep != None) + portList = rep.getEgressPortList() + self.assertTrue(len(portList), 2) + self.assertTrue("2" in portList) + self.assertTrue("3" in portList) + self.assertEqual(rep.getSamplePacket(), "0010203232..") + self.assertEqual(rep.getBlackHoledPacketCount(), 100) + self.assertEqual(rep.getIngressPort(), "1") + + def test_get_black_hole_event_report_missing_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_method) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_invalid_method(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_invalid_method) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_missing_asic(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_asic) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_missing_result(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_result) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_empty_result(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_empty_result) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_result_array(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_result_array) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_missing_timestamp(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_timestamp) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_missing_ingress_port(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_ingress_port) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_missing_egress_port_list(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_egress_port_list) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_missing_bhpc(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_bhpc) + self.assertEqual(ret, False) + + def test_get_black_hole_event_report_missing_sample_packet(self): + rep = BHDParser() + ret = rep.process(self.get_black_hole_event_report_missing_sample_packet) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_1(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_1) + self.assertEqual(ret, True) + rep = rep.getSFlowSamplingStatus() + self.assertTrue(rep != None) + i = 0 + for x in rep: + comp = self.get_sflow_sampling_status_1["report"]["data"][i] + self.assertTrue(x.getPort() == comp["port"]) + self.assertTrue(x.getSFlowSamplingEnabled() == comp["sflow-sampling-enabled"]) + self.assertTrue(x.getSampledPacketCount() == comp["sampled-packet-count"]) + self.assertTrue(x.getBlackHoledPacketCount() == comp["black-holed-packet-count"]) + i = i + 1 + self.assertEqual(i, 2) + + def test_get_sflow_sampling_status_missing_method(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_method) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_timestamp(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_timestamp) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_invalid_timestamp(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_invalid_timestamp) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_invalid_method(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_invalid_method) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_asic(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_asic) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_data(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_data) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_data_object(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_data_object) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_data_string(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_data_string) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_result(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_result) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_empty_result(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_empty_result) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_result_array(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_result_array) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_port(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_port) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_sampling_enabled(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_sampling_enabled) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_sampled_packet_count(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_sampled_packet_count) + self.assertEqual(ret, False) + + def test_get_sflow_sampling_status_missing_black_holed_packet_count(self): + rep = BHDParser() + ret = rep.process(self.get_sflow_sampling_status_missing_black_holed_packet_count) + self.assertEqual(ret, False) + +if __name__ == "__main__": + unittest.main() diff --git a/broadview_lib/bhd/black_hole.py b/broadview_lib/bhd/black_hole.py new file mode 100644 index 0000000..f709908 --- /dev/null +++ b/broadview_lib/bhd/black_hole.py @@ -0,0 +1,63 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +import agent_sampling_params +import sflow_sampling_params + +class BlackHole(): + + AgentSampling = 1 + SFlowSampling = 2 + + def __init__(self): + self._portList = [] + self._samplingMethod = None + self._samplingParams = None + + def getSamplingMethod(self): + return self._samplingMethod + + def getPortList(self): + return self._portList + + def getSamplingParams(self): + return self._samplingParams + + def __repr__(self): + return "get-black-hole" + + def parse(self, data): + ret = True + if "sampling-method" in data: + if data["sampling-method"] == "sflow": + self._samplingMethod = BlackHole.SFlowSampling + self._samplingParams = sflow_sampling_params.SFlowSamplingParams() + elif data["sampling-method"] == "agent": + self._samplingMethod = BlackHole.AgentSampling + self._samplingParams = agent_sampling_params.AgentSamplingParams() + else: + ret = False + else: + ret = False + + if ret: + if not "port-list" in data: + ret = False + else: + self._portList = data["port-list"] + + if ret: + ret = self._samplingParams.parse(data) + + return ret diff --git a/broadview_lib/bhd/black_hole_event_report.py b/broadview_lib/bhd/black_hole_event_report.py new file mode 100644 index 0000000..095bec7 --- /dev/null +++ b/broadview_lib/bhd/black_hole_event_report.py @@ -0,0 +1,60 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +class BlackHoleEventReport(): + + def __init__(self): + self._ingressPort = None + self._egressPortList = [] + self._blackHoledPacketCount = 0 + self._samplePacket = None + + def getIngressPort(self): + return self._ingressPort + + def getEgressPortList(self): + return self._egressPortList + + def getBlackHoledPacketCount(self): + return self._blackHoledPacketCount + + def getSamplePacket(self): + return self._samplePacket + + def __repr__(self): + return "get-black-hole-event-report" + + def parse(self, data): + ret = True + if "ingress-port" in data: + self._ingressPort = data["ingress-port"] + else: + ret = False + + if "egress-port-list" in data: + self._egressPortList = data["egress-port-list"] + else: + ret = False + + if "black-holed-packet-count" in data: + self._blackHoledPacketCount = data["black-holed-packet-count"] + else: + ret = False + + if "sample-packet" in data: + self._samplePacket = data["sample-packet"] + else: + ret = False + + return ret diff --git a/broadview_lib/bhd/sflow_sampling_params.py b/broadview_lib/bhd/sflow_sampling_params.py new file mode 100644 index 0000000..f8bf0d0 --- /dev/null +++ b/broadview_lib/bhd/sflow_sampling_params.py @@ -0,0 +1,88 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +class SFlowSamplingParams(): + + def __init__(self): + self._vlanId = 0 + self._dstIP = None + self._srcUDPPort = 0 + self._dstUDPPort = 0 + self._mirrorPort = None + self._samplePoolSize = 0 + + def getVLANId(self): + return self._vlanId + + def getDstIP(self): + return self._dstIP + + def getSrcUDPPort(self): + return self._srcUDPPort + + def getDstUDPPort(self): + return self._dstUDPPort + + def getMirrorPort(self): + return self._mirrorPort + + def getSamplePoolSize(self): + return self._samplePoolSize + + def __repr__(self): + return "sflow-sampling-params" + + def parse(self, data): + ret = True + + if "sampling-params" in data: + p = data["sampling-params"] + else: + ret = False + + if ret: + if "mirror-port" in p: + self._mirrorPort = p["mirror-port"] + else: + ret = False + if "sample-pool-size" in p: + self._samplePoolSize = p["sample-pool-size"] + else: + ret = False + if "encapsulation-params" in p: + # embedded object, note we are changing p here + p = p["encapsulation-params"] + else: + ret = False + if "vlan-id" in p: + self._vlanId = p["vlan-id"] + else: + ret = False + + if "destination-ip" in p: + self._dstIP = p["destination-ip"] + else: + ret = False + + if "source-udp-port" in p: + self._srcUDPPort = p["source-udp-port"] + else: + ret = False + + if "destination-udp-port" in p: + self._dstUDPPort = p["destination-udp-port"] + else: + ret = False + + return ret diff --git a/broadview_lib/bhd/sflow_sampling_status.py b/broadview_lib/bhd/sflow_sampling_status.py new file mode 100644 index 0000000..6b61f17 --- /dev/null +++ b/broadview_lib/bhd/sflow_sampling_status.py @@ -0,0 +1,80 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + + +class SFlowSamplingStatusEntry(): + def __init__(self): + self._port = None + self._sflowSamplingEnabled = False + self._sampledPacketCount = 0 + self._blackHoledPacketCount = 0 + + def getSFlowSamplingEnabled(self): + return self._sflowSamplingEnabled + + def getPort(self): + return self._port + + def getSampledPacketCount(self): + return self._sampledPacketCount + + def getBlackHoledPacketCount(self): + return self._blackHoledPacketCount + +class SFlowSamplingStatus(): + + def __init__(self): + self.__table = [] + + def __iter__(self): + self.__n = 0 + return self + + def next(self): + if self.__n >= len(self.__table): + raise StopIteration + else: + n = self.__n + self.__n += 1 + return self.__table[n] + + def __repr__(self): + return "sflow-sampling-status" + + def parse(self, data): + ret = True + if not "data" in data: + ret = False + else: + for y in data["data"]: + val = SFlowSamplingStatusEntry() + if not "port" in y: + ret = False + break + val._port = y["port"] + if not "sflow-sampling-enabled" in y: + ret = False + break + val._sflowSamplingEnabled = y["sflow-sampling-enabled"] == 1 + if not "sampled-packet-count" in y: + ret = False + break + val._sampledPacketCount = y["sampled-packet-count"] + if not "black-holed-packet-count" in y: + ret = False + break + val._blackHoledPacketCount = y["black-holed-packet-count"] + self.__table.append(val) + + return ret diff --git a/broadview_lib/config/bhd.py b/broadview_lib/config/bhd.py new file mode 100644 index 0000000..6b3b585 --- /dev/null +++ b/broadview_lib/config/bhd.py @@ -0,0 +1,533 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +from agentapi import AgentAPI +from broadview_lib.bhd.bhd_parser import BHDParser +from broadview_lib.config.broadviewconfig import BroadViewBSTSwitches +import unittest + +class BlackHoleDetectionEnable(AgentAPI): + def __init__(self, host, port): + super(BlackHoleDetectionEnable, self).__init__() + self.setFeature("black-hole-detection") + self.setHttpMethod("POST") + self.setHost(host) + self.setPort(port) + self.__black_hole_detection_enable = False + self.__asic_id = "1" + + def setEnable(self, val): + self.__black_hole_detection_enable = val + + def setASIC(self, val): + self.__asic_id = val + + def send(self, timeout=30): + status, json = self._send(self.toDict(), timeout) + return status + + + def toDict(self): + ret = {} + params = {} + params["enable"] = 1 if self.__black_hole_detection_enable else 0 + ret["asic-id"] = self.__asic_id + ret["params"] = params + ret["method"] = "black-hole-detection-enable" + return ret + +class ConfigureBlackHole(AgentAPI): + def __init__(self, host, port): + super(ConfigureBlackHole, self).__init__() + self.setFeature("black-hole-detection") + self.setHttpMethod("POST") + self.setHost(host) + self.setPort(port) + self.__port_list = [] + self.__sampling_method = "agent" + self.__water_mark = 200 + self.__sample_periodicity = 15 + self.__sample_count = 10 + self.__vlan_id = 1 + self.__destination_ip = None + self.__source_udp_port = None + self.__destination_udp_port = None + self.__mirror_port = None + self.__sample_pool_size = None + self.__asic_id = "1" + + def setPortList(self, val): + self.__port_list = val + + def setSamplingMethod(self, val): + self.__sampling_method = val + + def setWaterMark(self, val): + self.__water_mark = val + + def setSamplePeriodicity(self, val): + self.__sample_periodicity = val + + def setSampleCount(self, val): + self.__sample_count = val + + def setVLANId(self, val): + self.__vlan_id = val + + def setDestinationIP(self, val): + self.__destination_ip = val + + def setSourceUDPPort(self, val): + self.__source_udp_port = val + + def setDestinationUDPPort(self, val): + self.__destination_udp_port = val + + def setMirrorPort(self, val): + self.__mirror_port = val + + def setSamplePoolSize(self, val): + self.__sample_pool_size = val + + def setASIC(self, val): + self.__asic_id = val + + def send(self, timeout=30): + status, json = self._send(self.toDict(), timeout) + return status + + def toDict(self): + ret = {} + params = {} + params["port-list"] = self.__port_list + params["sampling-method"] = self.__sampling_method + params["sampling-params"] = {} + if self.__sampling_method == "agent": + params["sampling-params"]["water-mark"] = self.__water_mark + params["sampling-params"]["sample-periodicity"] = self.__sample_periodicity + params["sampling-params"]["sample-count"] = self.__sample_count + else: + params["sampling-params"]["encapsulation-params"] = {} + params["sampling-params"]["encapsulation-params"]["vlan-id"] = self.__vlan_id + params["sampling-params"]["encapsulation-params"]["destination-ip"] = self.__destination_ip + params["sampling-params"]["encapsulation-params"]["source-udp-port"] = self.__source_udp_port + params["sampling-params"]["encapsulation-params"]["destination-udp-port"] = self.__destination_udp_port + params["sampling-params"]["mirror-port"] = self.__mirror_port + params["sampling-params"]["sample-pool-size"] = self.__sample_pool_size + ret["asic-id"] = self.__asic_id + ret["params"] = params + ret["method"] = "configure-black-hole" + return ret + +class CancelBlackHole(AgentAPI): + def __init__(self, host, port): + super(CancelBlackHole, self).__init__() + self.setFeature("black-hole-detection") + self.setHttpMethod("POST") + self.setHost(host) + self.setPort(port) + self.__id = 0 + self.__asic_id = "1" + + def setId(self, val): + self.__id = val + + def setASIC(self, val): + self.__asic_id = val + + def send(self, timeout=30): + status, json = self._send(self.toDict(), timeout) + return status + + def toDict(self): + ret = {} + params = {} + params["id"] = self.__id + ret["asic-id"] = self.__asic_id + ret["params"] = params + ret["method"] = "cancel-black-hole" + return ret + +''' + +Status/Reporting Requests + +''' + +class GetBlackHoleDetectionEnable(AgentAPI): + def __init__(self, host, port): + super(GetBlackHoleDetectionEnable, self).__init__() + self.setFeature("black-hole-detection") + self.setHttpMethod("POST") + self.setHost(host) + self.setPort(port) + self.__enable = False + self.__asic_id = "1" + self.__json = None + + def getEnable(self): + return self.__bhd_enable + + def getASIC(self): + return self.__asic_id + + def setASIC(self, val): + self.__asic_id = val + + def getJSON(self): + return self.__json + + def send(self, timeout=30): + status, json = self._send(self.toDict(), timeout) + if status == 200: + self.__version = json["version"] + res = json["result"] + self.__json = res + self.__enable = res["enable"] == 1 + return status + + def toDict(self): + ret = {} + params = {} + params["enable"] = 1 if self.__enable == True else 0 + ret["asic-id"] = self.__asic_id + ret["params"] = params + ret["method"] = "get-black-hole-detection-enable" + return ret + +class GetBlackHole(AgentAPI): + def __init__(self, host, port): + super(GetBlackHole, self).__init__() + self.setFeature("black-hole-detection") + self.setHttpMethod("POST") + self.setHost(host) + self.setPort(port) + self.__asic_id = "1" + self.__json = None + + def getASIC(self): + return self.__asic_id + + def setASIC(self, val): + self.__asic_id = val + + def getJSON(self): + return self.__json + + def send(self, timeout=30): + status, json = self._send(self.toDict(), timeout) + rep = None + if status == 200: + self.__json = json["result"] + rep = PTParser() + rep.process(json) + return status, rep + + def toDict(self): + ret = {} + params = {} + + ret["asic-id"] = self.__asic_id + ret["params"] = params + ret["method"] = "get-black-hole" + return ret + +class GetSFlowSamplingStatus(AgentAPI): + def __init__(self, host, port): + super(GetSFlowSamplingStatus, self).__init__() + self.setFeature("black-hole-detection") + self.setHttpMethod("POST") + self.setHost(host) + self.setPort(port) + self.__port_list = [] + self.__asic_id = "1" + self.__json = None + + def getASIC(self): + return self.__asic_id + + def setASIC(self, val): + self.__asic_id = val + + def setPortList(self, val): + self.__port_list = val + + def getJSON(self): + return self.__json + + def send(self, timeout=30): + status, json = self._send(self.toDict(), timeout) + rep = None + if status == 200: + self.__json = json["report"] + rep = PTParser() + rep.process(json) + return status, rep + + def toDict(self): + ret = {} + params = {} + params["port-list"] = self.__port_list + + ret["asic-id"] = self.__asic_id + ret["params"] = params + ret["method"] = "get-sflow-sampling-status" + return ret + +class TestBHDAPIParams(unittest.TestCase): + + def setUp(self): + pass + + def test_BlackHoleDetectionEnable(self): + sw = BroadViewBSTSwitches() + if len(sw): + for x in sw: + host = x["ip"] + port = x["port"] + break + else: + host = "192.168.3.1" + port = 8080 + + x = BlackHoleDetectionEnable(host, port) + d = x.toDict() + self.assertTrue("asic-id" in d) + self.assertTrue("params" in d) + self.assertTrue("method" in d) + self.assertTrue(x.getFeature() == "black-hole-detection") + self.assertTrue(x.getHttpMethod() == "POST") + self.assertTrue(x.getHost() == host) + self.assertTrue(x.getPort() == port) + self.assertTrue(d["asic-id"] == "1") + self.assertTrue(d["method"] == "black-hole-detection-enable") + + params = d["params"] + self.assertEqual(params["enable"], False) + + x.setEnable(True) + d = x.toDict() + + params = d["params"] + self.assertEqual(params["enable"], True) + + x.setEnable(False) + d = x.toDict() + + params = d["params"] + self.assertEqual(params["enable"], False) + + def test_ConfigureBlackHole(self): + sw = BroadViewBSTSwitches() + if len(sw): + for x in sw: + host = x["ip"] + port = x["port"] + break + else: + host = "192.168.3.1" + port = 8080 + + x = ConfigureBlackHole(host, port) + d = x.toDict() + self.assertTrue("asic-id" in d) + self.assertTrue("params" in d) + self.assertTrue("method" in d) + self.assertTrue(x.getFeature() == "black-hole-detection") + self.assertTrue(x.getHttpMethod() == "POST") + self.assertTrue(x.getHost() == host) + self.assertTrue(x.getPort() == port) + + params = d["params"] + samplingParams = params["sampling-params"] + self.assertTrue(d["asic-id"] == "1") + self.assertEqual(len(params["port-list"]), 0) + self.assertEqual(params["sampling-method"], "agent") + self.assertTrue(samplingParams["water-mark"] == 200) + self.assertTrue(samplingParams["sample-periodicity"] == 15) + self.assertTrue(samplingParams["sample-count"] == 10) + + x.setSamplingMethod("agent") + x.setPortList(["1","5","6","10-15"]) + x.setWaterMark(500) + x.setSamplePeriodicity(25) + x.setSampleCount(50) + x.setVLANId(4000) + x.setDestinationIP("10.0.0.4") + x.setSourceUDPPort(1234) + x.setDestinationUDPPort(5678) + x.setMirrorPort(8) + x.setSamplePoolSize(5) + d = x.toDict() + params = d["params"] + samplingParams = params["sampling-params"] + + self.assertEqual(params["sampling-method"], "agent") + self.assertTrue("port-list" in params) + self.assertTrue("water-mark" in samplingParams) + self.assertTrue("sample-periodicity" in samplingParams) + self.assertTrue("sample-count" in samplingParams) + self.assertTrue(not "vlan-id" in samplingParams) + self.assertTrue(not "destination-ip" in samplingParams) + self.assertTrue(not "source-udp-port" in samplingParams) + self.assertTrue(not "destination-udp-port" in samplingParams) + self.assertTrue(not "mirror-port" in samplingParams) + self.assertTrue(not "sample-pool-size" in samplingParams) + + self.assertTrue(samplingParams["water-mark"] == 500) + self.assertTrue(samplingParams["sample-periodicity"] == 25) + self.assertTrue(samplingParams["sample-count"] == 50) + self.assertTrue(len(params["port-list"]) == 4) + self.assertTrue("1" in params["port-list"]) + self.assertTrue("5" in params["port-list"]) + self.assertTrue("6" in params["port-list"]) + self.assertTrue("10-15" in params["port-list"]) + + x.setSamplingMethod("sflow") + d = x.toDict() + params = d["params"] + samplingParams = params["sampling-params"] + encapsulationParams = samplingParams["encapsulation-params"] + + self.assertEqual(params["sampling-method"], "sflow") + self.assertTrue("port-list" in params) + self.assertTrue(not "water-mark" in samplingParams) + self.assertTrue(not "sample-periodicity" in samplingParams) + self.assertTrue(not "sample-count" in samplingParams) + self.assertTrue("vlan-id" in encapsulationParams) + self.assertTrue("destination-ip" in encapsulationParams) + self.assertTrue("source-udp-port" in encapsulationParams) + self.assertTrue("destination-udp-port" in encapsulationParams) + self.assertTrue("mirror-port" in samplingParams) + self.assertTrue("sample-pool-size" in samplingParams) + + self.assertTrue(encapsulationParams["vlan-id"] == 4000) + self.assertTrue(encapsulationParams["destination-ip"] == "10.0.0.4") + self.assertTrue(encapsulationParams["source-udp-port"] == 1234) + self.assertTrue(encapsulationParams["destination-udp-port"] == 5678) + self.assertTrue(samplingParams["mirror-port"] == 8) + self.assertTrue(samplingParams["sample-pool-size"] == 5) + self.assertTrue(len(params["port-list"]) == 4) + self.assertTrue("1" in params["port-list"]) + self.assertTrue("5" in params["port-list"]) + self.assertTrue("6" in params["port-list"]) + self.assertTrue("10-15" in params["port-list"]) + + def test_CancelBlackHole(self): + sw = BroadViewBSTSwitches() + if len(sw): + for x in sw: + host = x["ip"] + port = x["port"] + break + else: + host = "192.168.3.1" + port = 8080 + + x = CancelBlackHole(host, port) + d = x.toDict() + self.assertTrue("asic-id" in d) + self.assertTrue("params" in d) + self.assertTrue("method" in d) + self.assertTrue(x.getFeature() == "black-hole-detection") + self.assertTrue(x.getHttpMethod() == "POST") + self.assertTrue(x.getHost() == host) + self.assertTrue(x.getPort() == port) + self.assertTrue(d["asic-id"] == "1") + self.assertTrue(d["method"] == "cancel-black-hole") + + def test_GetBlackHoleDetectionEnable(self): + sw = BroadViewBSTSwitches() + if len(sw): + for x in sw: + host = x["ip"] + port = x["port"] + break + else: + host = "192.168.3.1" + port = 8080 + + x = GetBlackHoleDetectionEnable(host, port) + d = x.toDict() + self.assertTrue("asic-id" in d) + self.assertTrue("params" in d) + self.assertTrue("method" in d) + self.assertTrue(x.getFeature() == "black-hole-detection") + self.assertTrue(x.getHttpMethod() == "POST") + self.assertTrue(x.getHost() == host) + self.assertTrue(x.getPort() == port) + self.assertTrue(d["asic-id"] == "1") + self.assertTrue(d["method"] == "get-black-hole-detection-enable") + + def test_GetBlackHole(self): + sw = BroadViewBSTSwitches() + if len(sw): + for x in sw: + host = x["ip"] + port = x["port"] + break + else: + host = "192.168.3.1" + port = 8080 + + x = GetBlackHole(host, port) + d = x.toDict() + self.assertTrue("asic-id" in d) + self.assertTrue("params" in d) + self.assertTrue("method" in d) + self.assertTrue(x.getFeature() == "black-hole-detection") + self.assertTrue(x.getHttpMethod() == "POST") + self.assertTrue(x.getHost() == host) + self.assertTrue(x.getPort() == port) + self.assertTrue(d["asic-id"] == "1") + self.assertTrue(d["method"] == "get-black-hole") + + def test_GetSFlowSamplingStatus(self): + sw = BroadViewBSTSwitches() + if len(sw): + for x in sw: + host = x["ip"] + port = x["port"] + break + else: + host = "192.168.3.1" + port = 8080 + + x = GetSFlowSamplingStatus(host, port) + d = x.toDict() + self.assertTrue("asic-id" in d) + self.assertTrue("params" in d) + self.assertTrue("method" in d) + self.assertTrue(x.getFeature() == "black-hole-detection") + self.assertTrue(x.getHttpMethod() == "POST") + self.assertTrue(x.getHost() == host) + self.assertTrue(x.getPort() == port) + self.assertTrue(d["asic-id"] == "1") + self.assertTrue(d["method"] == "get-sflow-sampling-status") + params = d["params"] + self.assertTrue("port-list" in params) + self.assertTrue(len(params["port-list"]) == 0) + + x.setPortList(["1", "11", "3", "4-10"]) + d = x.toDict() + params = d["params"] + + self.assertTrue("1" in params["port-list"]) + self.assertTrue("11" in params["port-list"]) + self.assertTrue("3" in params["port-list"]) + self.assertTrue("4-10" in params["port-list"]) + self.assertTrue(len(params["port-list"]) == 4) + +if __name__ == "__main__": + unittest.main() diff --git a/broadview_lib/tools/bv-bhdctl-examples.sh b/broadview_lib/tools/bv-bhdctl-examples.sh new file mode 100644 index 0000000..2f01dca --- /dev/null +++ b/broadview_lib/tools/bv-bhdctl-examples.sh @@ -0,0 +1,29 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +host=10.14.244.128 +port=8082 + +echo "********** get-system-feature **********" +python bv-ctl.py get-system-feature timeout:30 host:$host port:$port +echo "********** get-switch-properties **********" +python bv-ctl.py get-switch-properties timeout:30 host:$host port:$port + +python bv-bhdctl.py configure sampling-method:agent sample-count:100 sample-periodicity:45 port-list:1,2,3,4 water-mark:45 timeout:30 host:$host port:$port +python bv-bhdctl.py configure sampling-method:sflow vlan-id:1 dst-ip:10.0.0.4 src-udp-port:4567 dst-udp-port:1234 mirror-port:3 sample-pool-size:100 timeout:30 host:$host port:$port +python bv-bhdctl.py get-detection-enable timeout:30 host:$host port:$port +python bv-bhdctl.py get timeout:30 host:$host port:$port +python bv-bhdctl.py get-sflow-sampling-status port-list:1,2,3,4 timeout:30 host:$host port:$port +python bv-bhdctl.py cancel timeout:30 host:$host port:$port +python bv-bhdctl.py detection-enable enable:true timeout:30 host:$host port:$port diff --git a/broadview_lib/tools/bv-bhdctl.py b/broadview_lib/tools/bv-bhdctl.py new file mode 100644 index 0000000..bb64346 --- /dev/null +++ b/broadview_lib/tools/bv-bhdctl.py @@ -0,0 +1,379 @@ +#!/usr/bin/python + +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +from broadview_lib.config.bhd import * +import sys +import json + +class BHDCommand(): + def __init__(self): + self._timeout = 30 + self.__cmds = { + "detection-enable" : self.handleDetectionEnable, + "configure" : self.handleConfigure, + "cancel" : self.handleCancel, + "get-detection-enable" : self.handleGetDetectionEnable, + "get" : self.handleGet, + "get-sflow-sampling-status" : self.handleGetSFlowSamplingStatus, + "help": self.handleHelp, + } + + self.__help = { + "detection-enable" : self.helpDetectionEnable, + "configure" : self.helpConfigure, + "cancel" : self.helpCancel, + "get-detection-enable" : self.helpGetDetectionEnable, + "get" : self.helpGet, + "get-sflow-sampling-status" : self.helpGetSFlowSamplingStatus, + } + + def getTimeout(self, args): + timeout = 30 + usage = False + for x in args: + if "timeout:" in x: + v = x.split(":") + if len(v) == 2: + timeout = int(v[1]) + else: + print "invalid timeout" + usage = True + return usage, timeout + + def getASICHostPort(self, args): + usage = False + asic = "1" + port = 8080 + host = None + + for x in args: + if "asic-id:" in x: + v = x.split(":") + if len(v) == 2: + asic = v[1] + else: + print "invalid asic-id" + usage = True + if "host:" in x: + v = x.split(":") + if len(v) == 2: + host = v[1] + else: + print "invalid host" + usage = True + if "port:" in x: + v = x.split(":") + if len(v) == 2: + port = int(v[1]) + else: + print "invalid port" + usage = True + + if host == None: + # host is required + print "missing host" + usage = True + + return usage, asic, host, port + + def usage(self): + print "usage: %s cmd host:ipv4 [timeout:seconds] [port:port] [asic-id:id] [args]" % (sys.argv[0]) + print + print "Commands:" + print + for key, val in self.__help.iteritems(): + print + val(key) + + def handleHelp(self, args): + usage = True + + if len(args): + cmd = args[0] + if cmd in self.__help: + self.__help[cmd](cmd) + usage = None + + return usage, None + + def handleUnimplemented(self, args): + usage = True + ret = None + return usage, ret + + def helpUnimplemented(self, name): + print name + print + print "The {} command is currently not supported and may become deprecated".format(name) + + def helpDetectionEnable(self, name): + print name, "[args]" + print + print "args:" + print + print " enable:[true|false]" + + def handleDetectionEnable(self, args): + usage = False + usage, asic, host, port = self.getASICHostPort(args) + usage, self._timeout = self.getTimeout(args) + if not usage: + x = BlackHoleDetectionEnable(host, port) + x.setASIC(asic) + for arg in args: + if "enable:" in arg: + v = arg.split(":") + if len(v) == 2: + if v[1] == "true": + x.setEnable(True) + elif v[1] == "false": + x.setEnable(False) + else: + print "invalid enable argument" + self.helpDetectionEnable("detection-enable") + else: + print "invalid enable: bad argument count" + status = x.send(timeout=self._timeout) + if status != 200: + print "failure: %d" % (status) + + ret = None + return usage, ret + + def handleConfigure(self, args): + usage = False + usage, asic, host, port = self.getASICHostPort(args) + if not usage: + x = ConfigurePacketTraceDropReason(host, port) + for arg in args: + if "sampling-method:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setSamplingMethod(v[1]) + else: + print "invalid sampling-method: bad argument count" + usage = True + elif "port-list:" in arg: + v = arg.split(":") + if len(v) == 2: + v2 = v[1].split(",") + port_list = [] + for y in v2: + port_list.append(x) + x.setPortList(port_list) + else: + print "invalid port-list: bad argument count" + usage = True + elif "water-mark:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setWaterMark(int(v[1])) + else: + print "invalid water-mark: bad argument count" + usage = True + elif "sample-periodicity:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setSamplePeriodicity(int(v[1])) + else: + print "invalid sample-periodicity: bad argument count" + usage = True + elif "sample-count:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setSampleCount(int(v[1])) + else: + print "invalid sample-count: bad argument count" + usage = True + elif "dst-ip:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setDestinationIP(v[1]) + else: + print "invalid dst-ip: bad argument count" + usage = True + elif "src-udp-port:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setSourceUDPPort(int(v[1])) + else: + print "invalid src-udp-port: bad argument count" + usage = True + elif "dst-udp-port:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setDestinationUDPPort(int(v[1])) + else: + print "invalid dst-udp-port: bad argument count" + usage = True + elif "mirror-port:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setMirrorPort(int(v[1])) + else: + print "invalid mirror-port: bad argument count" + usage = True + elif "sample-pool-size:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setSamplePoolSize(int(v[1])) + else: + print "invalid sample-pool-size: bad argument count" + usage = True + elif "vlan-id:" in arg: + v = arg.split(":") + if len(v) == 2: + x.setVLANId(int(v[1])) + else: + print "invalid vlan-id: bad argument count" + usage = True + + x.setASIC(asic) + status = x.send(self._timeout) + if status != 200: + print "failure: %d" % (status) + + ret = None + return usage, ret + + def helpConfigure(self, name): + print name, "[args]" + print + print "args:" + print + print " sampling-method:[agent|sflow]" + print " water-mark:integer" + print " port-list:port[,port][,port]...[,port]" + print " sample-periodicity:[integer]" + print " sample-count:n" + print " vlan-id:id" + print " dst-ip:ipv4" + print " src-udp-port:integer" + print " dst-udp-port:integer" + print " mirror-port:integer" + print " sample-pool-size:integer" + + def handleCancel(self, args): + usage = False + usage, asic, host, port = self.getASICHostPort(args) + if not usage: + x = CancelPacketTraceProfile(host, port) + x.setASIC(asic) + status = x.send(self._timeout) + if status != 200: + print "failure: %d" % (status) + + ret = None + return usage, ret + + def helpCancel(self, name): + print name + + def handleGetDetectionEnable(self, args): + usage = False + usage, asic, host, port = self.getASICHostPort(args) + if not usage: + x = GetBlackHoleDetectionEnable(host, port) + x.setASIC(asic) + status = x.send(self._timeout) + if status == 200: + ret = json.dumps(x.getJSON()) + print ret + else: + print "failure: %d" % (status) + + ret = None + return usage, ret + + def helpGetDetectionEnable(self, name): + print name + + def handleGet(self, args): + usage = False + usage, asic, host, port = self.getASICHostPort(args) + if not usage: + x = GetBlackHole(host, port) + x.setASIC(asic) + status = x.send(self._timeout) + if status == 200: + ret = json.dumps(x.getJSON()) + print ret + else: + print "failure: %d" % (status) + + ret = None + return usage, ret + + def helpGet(self, name): + print name + + def handleGetSFlowSamplingStatus(self, args): + usage = False + usage, asic, host, port = self.getASICHostPort(args) + if not usage: + x = GetSFlowSamplingStatus(host, port) + for arg in args: + if "port-list:" in arg: + v = arg.split(":") + if len(v) == 2: + v2 = v[1].split(",") + port_list = [] + for y in v2: + port_list.append(x) + x.setPortList(port_list) + else: + print "invalid port-list: bad argument count" + usage = True + + x.setASIC(asic) + status = x.send(self._timeout) + if status == 200: + ret = json.dumps(x.getJSON()) + print ret + else: + print "failure: %d" % (status) + + ret = None + return usage, ret + + def helpGetSFlowSamplingStatus(self, name): + print name, "[args]" + print + print "args:" + print + print " port-list:port[,port][,port]...[,port]" + + def isCmd(self, cmd): + return cmd in self.__cmds + + def handle(self, args): + usage = True + ret = {} + status = False + if len(args): + cmd = args.pop(0) + if self.isCmd(cmd): + usage, ret = self.__cmds[cmd](args) + return usage, ret + +def main(argv): + x = BHDCommand() + usage, ret = x.handle(argv) + if usage: + x.usage() + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/broadview_lib/tools/bv-ctl-examples.sh b/broadview_lib/tools/bv-ctl-examples.sh new file mode 100644 index 0000000..e91e384 --- /dev/null +++ b/broadview_lib/tools/bv-ctl-examples.sh @@ -0,0 +1,22 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +host=10.14.244.128 +port=8082 + +echo "********** get-system-feature **********" +python bv-ctl.py get-system-feature timeout:30 host:$host port:$port +echo "********** get-switch-properties **********" +python bv-ctl.py get-switch-properties timeout:30 host:$host port:$port + diff --git a/broadview_lib/tools/bv-ptctl-examples.sh b/broadview_lib/tools/bv-ptctl-examples.sh new file mode 100644 index 0000000..64e370b --- /dev/null +++ b/broadview_lib/tools/bv-ptctl-examples.sh @@ -0,0 +1,39 @@ +# (C) Copyright Broadcom Corporation 2016 +# +# 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. + +host=10.14.244.128 +port=8082 + +echo "********** get-system-feature **********" +python bv-ctl.py get-system-feature timeout:30 host:$host port:$port +echo "********** get-switch-properties **********" +python bv-ctl.py get-switch-properties timeout:30 host:$host port:$port + +echo "********** pt cfg-feature **********" +python bv-ptctl.py cfg-feature timeout:30 host:$host port:$port enable +echo "********** pt get-feature **********" +python bv-ptctl.py get-feature timeout:30 host:$host port:$port +echo "********** pt cfg-feature **********" +python bv-ptctl.py cfg-feature timeout:30 host:$host port:$port disable +echo "********** pt get-feature **********" +python bv-ptctl.py get-feature timeout:30 host:$host port:$port +echo "********** pt cancel-profile **********" +python bv-ptctl.py cancel-profile timeout:30 host:$host port:$port +echo "********** pt cancel-lag-resolution **********" +python bv-ptctl.py cancel-lag-resolution timeout:30 host:$host port:$port +echo "********** pt cancel-ecmp-resolution **********" +python bv-ptctl.py cancel-ecmp-resolution timeout:30 host:$host port:$port +echo "********** pt get-profile **********" +python bv-ptctl.py get-profile drop-packet:1 collection-interval:45 timeout:30 host:$host port:$port + diff --git a/broadview_lib/tools/examples.sh b/broadview_lib/tools/examples.sh index bf26255..2011193 100644 --- a/broadview_lib/tools/examples.sh +++ b/broadview_lib/tools/examples.sh @@ -16,9 +16,9 @@ host=10.14.244.128 port=8082 echo "********** get-system-feature **********" -python bv-ctl.py get-system-feature timeout:30 host:$host port:$port +python bv-ctl.py get-system-feature timeout:30 host:$host port:$port echo "********** get-switch-properties **********" -python bv-ctl.py get-switch-properties timeout:30 host:$host port:$port +python bv-ctl.py get-switch-properties timeout:30 host:$host port:$port echo "********** bst cfg-feature **********" python bv-bstctl.py cfg-feature timeout:30 host:$host port:$port enable send_async_reports @@ -58,21 +58,3 @@ echo "********** bst cfg-thresholds ingress-port-service-pool **********" python bv-bstctl.py cfg-thresholds host:$host port:$port ingress-port-service-pool:"4":2:50505 echo "********** bst cfg-thresholds ingress-service-pool **********" python bv-bstctl.py cfg-thresholds host:$host port:$port ingress-service-pool:2:56783 - -echo "********** pt cfg-feature **********" -python bv-ptctl.py cfg-feature timeout:30 host:$host port:$port enable -echo "********** pt get-feature **********" -python bv-ptctl.py get-feature timeout:30 host:$host port:$port -echo "********** pt cfg-feature **********" -python bv-ptctl.py cfg-feature timeout:30 host:$host port:$port disable -echo "********** pt get-feature **********" -python bv-ptctl.py get-feature timeout:30 host:$host port:$port -echo "********** pt cancel-profile **********" -python bv-ptctl.py cancel-profile timeout:30 host:$host port:$port -echo "********** pt cancel-lag-resolution **********" -python bv-ptctl.py cancel-lag-resolution timeout:30 host:$host port:$port -echo "********** pt cancel-ecmp-resolution **********" -python bv-ptctl.py cancel-ecmp-resolution timeout:30 host:$host port:$port -echo "********** pt get-profile **********" -python bv-ptctl.py get-profile drop-packet:1 collection-interval:45 timeout:30 host:$host port:$port -