Skip to content

Commit ef126ea

Browse files
committed
Black hole: add an option to stop stack in case of black hole
Until now (and still the default) sink cost set to the 254 is the way to prevent the black hole case. But with this option, it allows to stop the stack instead. It allows testing on large scale networks. Also add the cost in configure node for easy diagnostic.
1 parent 6f9fc86 commit ef126ea

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

python_transport/wirepas_gateway/configure_node.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ def list_sinks(self):
183183
print("[%s]: %s" % (key, binascii.hexlify(config[key])))
184184
else:
185185
print("[%s]: %s" % (key, config[key]))
186+
print("[cost]: %d" % (sink.cost))
186187
print("===================================")
187188

188189

python_transport/wirepas_gateway/transport_service.py

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def __init__(
3535
minimum_sink_cost,
3636
max_buffered_packets,
3737
max_delay_without_publish,
38+
stop_stack = False
3839
):
3940
"""
4041
Thread monitoring the connection with the MQTT broker.
@@ -53,6 +54,7 @@ def __init__(
5354
rising the sink costs
5455
max_delay_without_publish: the maximum delay without any successful publish (with
5556
something in the queue before rising the sink costs
57+
stop_stack: stop the stack instead of increasing the sink cost in case of black hole
5658
"""
5759
Thread.__init__(self)
5860

@@ -71,11 +73,20 @@ def __init__(
7173
self.minimum_sink_cost = minimum_sink_cost
7274
self.max_buffered_packets = max_buffered_packets
7375
self.max_delay_without_publish = max_delay_without_publish
76+
self.stop_stack = stop_stack
7477

7578
def _set_sinks_cost(self, cost):
7679
for sink in self.sink_manager.get_sinks():
7780
sink.cost = cost
7881

82+
def _stop_sinks(self):
83+
for sink in self.sink_manager.get_sinks():
84+
sink.write_config({"started": False})
85+
86+
def _start_sinks(self):
87+
for sink in self.sink_manager.get_sinks():
88+
sink.write_config({"started": True})
89+
7990
def _set_sinks_cost_high(self):
8091
self._set_sinks_cost(self.SINK_COST_HIGH)
8192

@@ -113,22 +124,34 @@ def run(self):
113124
if not self.disconnected:
114125
# Check if a condition to declare "back hole" is met
115126
if self._is_publish_delay_over() or self._is_buffer_threshold_reached():
116-
logging.info("Increasing sink cost of all sinks")
117-
logging.debug(
127+
if self.stop_stack:
128+
logging.info("Black hole detected, stop all stacks")
129+
self._stop_sinks()
130+
else:
131+
logging.info("Increasing sink cost of all sinks")
132+
self._set_sinks_cost_high()
133+
134+
logging.info(
118135
"Last publish: %s Queue Size %s",
119136
self.mqtt_wrapper.publish_waiting_time_s,
120137
self.mqtt_wrapper.publish_queue_size,
121138
)
122139

123-
self._set_sinks_cost_high()
124140
self.disconnected = True
125141
else:
126142
if self.mqtt_wrapper.publish_queue_size == 0:
127143
# Network is back, put the connection back
128144
logging.info(
129-
"Connection is back, decreasing sink cost of all sinks"
145+
"Connection is back, black hole is finished"
130146
)
131-
self._set_sinks_cost_low()
147+
148+
if self.stop_stack:
149+
logging.info("Restart all sinks")
150+
self._start_sinks()
151+
else:
152+
logging.info("Decreasing sink cost")
153+
self._set_sinks_cost_low()
154+
132155
self.disconnected = False
133156

134157
# Wait for period
@@ -146,14 +169,16 @@ def initialize_sink(self, name):
146169
Args:
147170
name: name of sink to initialize
148171
"""
149-
sink = self.sink_manager.get_sink(name)
172+
# It is only required if black hole is managed by sink cost
173+
if not self.stop_stack:
174+
sink = self.sink_manager.get_sink(name)
150175

151-
logging.info("Initialize sinkCost of sink %s", name)
152-
if sink is not None:
153-
if self.disconnected:
154-
sink.cost = self.SINK_COST_HIGH
155-
else:
156-
sink.cost = self.minimum_sink_cost
176+
logging.info("Initialize sinkCost of sink %s", name)
177+
if sink is not None:
178+
if self.disconnected:
179+
sink.cost = self.SINK_COST_HIGH
180+
else:
181+
sink.cost = self.minimum_sink_cost
157182

158183

159184
class TransportService(BusClient):
@@ -209,9 +234,10 @@ def __init__(self, settings, **kwargs):
209234

210235
if settings.buffering_max_buffered_packets > 0 or settings.buffering_max_delay_without_publish > 0:
211236
logging.info(
212-
" Black hole detection enabled: max_packets=%s packets, max_delay=%s",
237+
" Black hole detection enabled: max_packets=%s packets, max_delay=%s, stop_stack=%s",
213238
settings.buffering_max_buffered_packets,
214239
settings.buffering_max_delay_without_publish,
240+
settings.buffering_stop_stack
215241
)
216242
# Create and start a monitoring thread for black hole issue
217243
self.monitoring_thread = ConnectionToBackendMonitorThread(
@@ -221,6 +247,7 @@ def __init__(self, settings, **kwargs):
221247
settings.buffering_minimal_sink_cost,
222248
settings.buffering_max_buffered_packets,
223249
settings.buffering_max_delay_without_publish,
250+
settings.buffering_stop_stack
224251
)
225252
self.monitoring_thread.start()
226253

python_transport/wirepas_gateway/utils/argument_tools.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,16 @@ def add_buffering_settings(self):
388388
),
389389
)
390390

391+
self.buffering.add_argument(
392+
"--buffering_stop_stack",
393+
default=os.environ.get("WM_GW_BUFFERING_STOP_STACK", False),
394+
type=self.str2bool,
395+
help=(
396+
"When true, when a black hole is detected, stack is stopped instead of "
397+
" increasing the sink cost"
398+
),
399+
)
400+
391401
# This minimal sink cost could be moved somewhere as it can be used even
392402
# buffering limitation is not in use
393403
self.buffering.add_argument(

0 commit comments

Comments
 (0)