-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[bgpcfgd]: Dynamic BBR support #5626
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
from swsscommon import swsscommon | ||
|
||
from .log import log_err, log_info, log_crit | ||
from .manager import Manager | ||
from .utils import run_command | ||
|
||
|
||
class BBRMgr(Manager): | ||
""" This class initialize "BBR" feature for """ | ||
def __init__(self, common_objs, db, table): | ||
""" | ||
Initialize the object | ||
:param common_objs: common object dictionary | ||
:param db: name of the db | ||
:param table: name of the table in the db | ||
""" | ||
super(BBRMgr, self).__init__( | ||
common_objs, | ||
[("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost/bgp_asn"),], | ||
db, | ||
table, | ||
) | ||
self.enabled = False | ||
self.bbr_enabled_pgs = {} | ||
self.directory.put(self.db_name, self.table_name, 'status', "disabled") | ||
self.__init() | ||
|
||
def set_handler(self, key, data): | ||
""" Implementation of 'SET' command for this class """ | ||
if not self.enabled: | ||
log_info("BBRMgr::BBR is disabled. Drop the request") | ||
return True | ||
if not self.__set_validation(key, data): | ||
return True | ||
cmds = self.__set_prepare_config(data['status']) | ||
rv = self.cfg_mgr.push_list(cmds) | ||
if not rv: | ||
log_crit("BBRMgr::can't apply configuration") | ||
return True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. always return True? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. False means save it in the queue, and give it back to me next time, |
||
self.__restart_peers() | ||
return True | ||
|
||
def del_handler(self, key): | ||
""" Implementation of 'DEL' command for this class """ | ||
log_err("The '%s' table shouldn't be removed from the db" % self.table_name) | ||
|
||
def __init(self): | ||
""" Initialize BBRMgr. Extracted from constructor """ | ||
if not 'bgp' in self.constants: | ||
log_err("BBRMgr::Disabled: 'bgp' key is not found in constants") | ||
return | ||
if 'bbr' in self.constants['bgp'] and \ | ||
'enabled' in self.constants['bgp']['bbr'] and \ | ||
self.constants['bgp']['bbr']['enabled']: | ||
self.bbr_enabled_pgs = self.__read_pgs() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "BBR is adding `neighbor PEER_GROUP allowas-in 1' for all BGP peer-groups which points to T0" can you point me code where you identify if a peer group points to T0 or not? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. I use file constants |
||
if self.bbr_enabled_pgs: | ||
self.enabled = True | ||
self.directory.put(self.db_name, self.table_name, 'status', "enabled") | ||
log_info("BBRMgr::Initialized and enabled") | ||
else: | ||
log_info("BBRMgr::Disabled: no BBR enabled peers") | ||
else: | ||
log_info("BBRMgr::Disabled: not enabled in the constants") | ||
|
||
def __read_pgs(self): | ||
""" | ||
Read peer-group bbr settings from constants file | ||
:return: return bbr information from constant peer-group settings | ||
""" | ||
if 'peers' not in self.constants['bgp']: | ||
log_info("BBRMgr::no 'peers' was found in constants") | ||
return {} | ||
res = {} | ||
for peer_name, value in self.constants['bgp']['peers'].items(): | ||
if 'bbr' not in value: | ||
continue | ||
for pg_name, pg_afs in value['bbr'].items(): | ||
res[pg_name] = pg_afs | ||
return res | ||
|
||
def __set_validation(self, key, data): | ||
""" Validate set-command arguments | ||
:param key: key of 'set' command | ||
:param data: data of 'set' command | ||
:return: True is the parameters are valid, False otherwise | ||
""" | ||
if key != 'all': | ||
log_err("Invalid key '%s' for table '%s'. Only key value 'all' is supported" % (key, self.table_name)) | ||
return False | ||
if 'status' not in data: | ||
log_err("Invalid value '%s' for table '%s', key '%s'. Key 'status' in data is expected" % (data, self.table_name, key)) | ||
return False | ||
if data['status'] != "enabled" and data['status'] != "disabled": | ||
log_err("Invalid value '%s' for table '%s', key '%s'. Only 'enabled' and 'disabled' are supported" % (data, self.table_name, key)) | ||
return False | ||
return True | ||
|
||
def __set_prepare_config(self, status): | ||
""" | ||
Generate FFR configuration to apply changes | ||
:param status: either "enabled" or "disabled" | ||
:return: list of commands prepared for FRR | ||
""" | ||
bgp_asn = self.directory.get_slot("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME)["localhost"]["bgp_asn"] | ||
cmds = ["router bgp %s" % bgp_asn] | ||
prefix_of_commands = "" if status == "enabled" else "no " | ||
for af in ["ipv4", "ipv6"]: | ||
cmds.append(" address-family %s" % af) | ||
for pg_name in sorted(self.bbr_enabled_pgs.keys()): | ||
if af in self.bbr_enabled_pgs[pg_name]: | ||
cmds.append(" %sneighbor %s allowas-in 1" % (prefix_of_commands, pg_name)) | ||
return cmds | ||
|
||
def __restart_peers(self): | ||
""" Restart peer-groups which support BBR """ | ||
for peer_group in sorted(self.bbr_enabled_pgs.keys()): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why sort here? any reason? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Otherwise my test doesn't know what to expect (or I can use conversion to sets) and compare sets. I'm going to remove it after the batching change |
||
rc, out, err = run_command(["vtysh", "-c", "clear bgp peer-group %s soft in" % peer_group]) | ||
if rc != 0: | ||
log_value = peer_group, rc, out, err | ||
log_crit("BBRMgr::Can't restart bgp peer-group '%s'. rc='%d', out='%s', err='%s'" % log_value) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,5 +3,8 @@ | |
"localhost": { | ||
"type": "ToRRouter" | ||
} | ||
} | ||
} | ||
}, | ||
"CONFIG_DB__BGP_BBR": { | ||
"status": "enabled" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,8 @@ | |
"type": "LeafRouter", | ||
"sub_role": "BackEnd" | ||
} | ||
}, | ||
"CONFIG_DB__BGP_BBR": { | ||
"status": "disabled" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from mock import MagicMock | ||
|
||
|
||
swsscommon = MagicMock(CFG_DEVICE_METADATA_TABLE_NAME = "DEVICE_METADATA") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not use device metadata role to identify if a peer is a tor or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this adds additional maintaining cost. it is better to check if neighbor metadata is available or not, if it is available, then use it. otherwise, look for bbr definition. do you agree?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree here, sorry