From 137ce8dd46d313f15ee93ddbb5428d702aa61ed8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 06:24:34 +0200 Subject: Merging upstream version 10.0. Signed-off-by: Daniel Baumann --- tools/checkpatch.pl | 5 +- tools/checkpatch.sh | 3 +- tools/etc/frr/support_bundle_commands.conf | 10 +- tools/frr-llvm-cg.c | 2 +- tools/frr-reload.py | 99 ++++++------- tools/frr.in | 10 +- tools/frr.service.in | 8 +- tools/frr@.service.in | 8 +- tools/frr_babeltrace.py | 70 ++++++++++ tools/frrcommon.sh.in | 12 +- tools/frrinit.sh.in | 2 +- tools/gen_northbound_callbacks.c | 217 ++++++++++++++++++++++++----- tools/gen_yang_deviations.c | 2 +- tools/valgrind.supp | 9 ++ tools/watchfrr.sh.in | 4 +- 15 files changed, 338 insertions(+), 123 deletions(-) (limited to 'tools') diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl index d007c1d..ecae0e9 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -547,7 +547,7 @@ our $Operators = qr{ our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; our $Iterators = qr{ - frr_each|frr_each_safe|frr_each_from| + darr_foreach_p|darr_foreach_i|frr_each|frr_each_safe|frr_each_from| frr_with_mutex|frr_with_privs| LIST_FOREACH|LIST_FOREACH_SAFE| SLIST_FOREACH|SLIST_FOREACH_SAFE|SLIST_FOREACH_PREVPTR| @@ -555,7 +555,7 @@ our $Iterators = qr{ TAILQ_FOREACH|TAILQ_FOREACH_SAFE|TAILQ_FOREACH_REVERSE|TAILQ_FOREACH_REVERSE_SAFE| RB_FOREACH|RB_FOREACH_SAFE|RB_FOREACH_REVERSE|RB_FOREACH_REVERSE_SAFE| SPLAY_FOREACH| - FOR_ALL_INTERFACES|FOR_ALL_INTERFACES_ADDRESSES|JSON_FOREACH| + FOR_ALL_INTERFACES|JSON_FOREACH| LY_FOR_KEYS|LY_LIST_FOR|LY_TREE_FOR|LY_TREE_DFS_BEGIN|LYD_TREE_DFS_BEGIN| RE_DEST_FOREACH_ROUTE|RE_DEST_FOREACH_ROUTE_SAFE| RNODE_FOREACH_RE|RNODE_FOREACH_RE_SAFE| @@ -563,6 +563,7 @@ our $Iterators = qr{ SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE| SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE| AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI| + FOREACH_BE_CLIENT_BITS|FOREACH_MGMTD_BE_CLIENT_ID| LSDB_LOOP }x; diff --git a/tools/checkpatch.sh b/tools/checkpatch.sh index 6071f48..bf63057 100755 --- a/tools/checkpatch.sh +++ b/tools/checkpatch.sh @@ -3,7 +3,8 @@ usage="./checkpatch.sh " patch=$1 tree=$2 -checkpatch="$tree/tools/checkpatch.pl --no-tree -f" +scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" +checkpatch="$scriptdir/checkpatch.pl --no-tree -f" ignore="ldpd\|babeld" cwd=${PWD##*/} dirty=0 diff --git a/tools/etc/frr/support_bundle_commands.conf b/tools/etc/frr/support_bundle_commands.conf index b7a1708..b3889e8 100644 --- a/tools/etc/frr/support_bundle_commands.conf +++ b/tools/etc/frr/support_bundle_commands.conf @@ -34,6 +34,8 @@ show bgp nexthop show bgp vrf all summary show bgp vrf all ipv4 show bgp vrf all ipv6 +show bgp vrf all ipv4 vpn +show bgp vrf all ipv6 vpn show bgp vrf all neighbors show bgp evpn route @@ -78,9 +80,9 @@ show vrf show work-queues show debugging hashtable show running-config -show thread cpu -show thread poll -show thread timers +show event cpu +show event poll +show event timers show daemons show version CMD_LIST_END @@ -175,7 +177,7 @@ CMD_LIST_END PROC_NAME:ospf6 CMD_LIST_START show ipv6 ospf6 vrf all -show ipv6 ospf6 vrfs +show ipv6 ospf6 vrfs show ipv6 ospf6 vrf all border-routers show ipv6 ospf6 vrf all border-routers detail show ipv6 ospf6 vrf all database diff --git a/tools/frr-llvm-cg.c b/tools/frr-llvm-cg.c index 3a7222e..f366ba6 100644 --- a/tools/frr-llvm-cg.c +++ b/tools/frr-llvm-cg.c @@ -231,7 +231,7 @@ static void walk_const_fptrs(struct json_object *js_call, LLVMValueRef value, "%s: calls function pointer from unhandled const GEP\n", prefix); *hdr_written = true; - /* fallthru */ + fallthrough; default: /* to help the user / development */ if (!*hdr_written) { diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 3a478f6..73479c6 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -25,6 +25,7 @@ from collections import OrderedDict from ipaddress import IPv6Address, ip_network from pprint import pformat + # Python 3 def iteritems(d): return iter(d.items()) @@ -362,7 +363,7 @@ class Config(object): """ Return the parsed context as strings for display, log etc. """ - for (_, ctx) in sorted(iteritems(self.contexts)): + for _, ctx in sorted(iteritems(self.contexts)): print(str(ctx)) def save_contexts(self, key, lines): @@ -546,7 +547,6 @@ class Config(object): cur_ctx_lines = [] for line in self.lines: - if not line: continue @@ -647,7 +647,7 @@ def lines_to_config(ctx_keys, line, delete): ctx_keys = [] if line: - for (i, ctx_key) in enumerate(ctx_keys): + for i, ctx_key in enumerate(ctx_keys): cmd.append(" " * i + ctx_key) line = line.lstrip() @@ -725,7 +725,7 @@ def get_normalized_ipv6_line(line): def line_exist(lines, target_ctx_keys, target_line, exact_match=True): - for (ctx_keys, line) in lines: + for ctx_keys, line in lines: if ctx_keys == target_ctx_keys: if exact_match: if line == target_line: @@ -744,7 +744,7 @@ def bgp_delete_inst_move_line(lines_to_del): bgp_defult_inst = False bgp_vrf_inst = False - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: # Find bgp default inst if ( ctx_keys[0].startswith("router bgp") @@ -757,7 +757,7 @@ def bgp_delete_inst_move_line(lines_to_del): bgp_vrf_inst = True if bgp_defult_inst and bgp_vrf_inst: - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: # move bgp default inst to end if ( ctx_keys[0].startswith("router bgp") @@ -853,7 +853,6 @@ def bgp_delete_nbr_remote_as_line(lines_to_add): def bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict): - # This method handles deletion of bgp neighbor configs, # if there is neighbor to peer-group cmd is in delete list. # As 'no neighbor .* peer-group' deletes the neighbor, @@ -861,7 +860,7 @@ def bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict): # in error. lines_to_del_to_del = [] - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: if ( ctx_keys[0].startswith("router bgp") and line @@ -876,7 +875,7 @@ def bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict): if re_nb: lines_to_del_to_del.append((ctx_keys, line)) - for (ctx_keys, line) in lines_to_del_to_del: + for ctx_keys, line in lines_to_del_to_del: lines_to_del.remove((ctx_keys, line)) @@ -942,7 +941,7 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): # "router bgp 200 no neighbor uplink1 interface remote-as internal" # "router bgp 200 no neighbor underlay peer-group" - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: if ( ctx_keys[0].startswith("router bgp") and line @@ -999,13 +998,13 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict) return (lines_to_add, lines_to_del) - for (ctx_keys, line) in lines_to_del_to_app: + for ctx_keys, line in lines_to_del_to_app: lines_to_del.remove((ctx_keys, line)) lines_to_del.append((ctx_keys, line)) # {'router bgp 65001': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}, # 'router bgp 65001 vrf vrf1': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}} - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: if ( ctx_keys[0].startswith("router bgp") and line @@ -1023,7 +1022,7 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): del_dict[ctx_keys[0]][pg_key].append(re_nbr_pg.group(1)) lines_to_del_to_app = [] - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: if ( ctx_keys[0].startswith("router bgp") and line @@ -1043,10 +1042,10 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): if re_pg: lines_to_del_to_app.append((ctx_keys, line)) - for (ctx_keys, line) in lines_to_del_to_del: + for ctx_keys, line in lines_to_del_to_del: lines_to_del.remove((ctx_keys, line)) - for (ctx_keys, line) in lines_to_del_to_app: + for ctx_keys, line in lines_to_del_to_app: lines_to_del.remove((ctx_keys, line)) lines_to_del.append((ctx_keys, line)) @@ -1056,7 +1055,6 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del): def pim_delete_move_lines(lines_to_add, lines_to_del): - # Under interface context, if 'no ip pim' is present # remove subsequent 'no ip pim ' options as it # they are implicitly deleted by 'no ip pim'. @@ -1064,12 +1062,12 @@ def pim_delete_move_lines(lines_to_add, lines_to_del): # pending list. pim_disable = False - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: if ctx_keys[0].startswith("interface") and line and line == "ip pim": pim_disable = True if pim_disable: - for (ctx_keys, line) in lines_to_del: + for ctx_keys, line in lines_to_del: if ( ctx_keys[0].startswith("interface") and line @@ -1081,7 +1079,6 @@ def pim_delete_move_lines(lines_to_add, lines_to_del): def delete_move_lines(lines_to_add, lines_to_del): - lines_to_add, lines_to_del = bgp_delete_move_lines(lines_to_add, lines_to_del) lines_to_add, lines_to_del = pim_delete_move_lines(lines_to_add, lines_to_del) @@ -1089,13 +1086,12 @@ def delete_move_lines(lines_to_add, lines_to_del): def ignore_delete_re_add_lines(lines_to_add, lines_to_del): - # Quite possibly the most confusing (while accurate) variable names in history lines_to_add_to_del = [] lines_to_del_to_del = [] - index = 0 - for (ctx_keys, line) in lines_to_del: + index = -1 + for ctx_keys, line in lines_to_del: deleted = False # no form of route-map description command only @@ -1110,10 +1106,21 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): lines_to_del.remove((ctx_keys, line)) lines_to_del.insert(index, (ctx_keys, "description")) + # interface x ; description blah + # no form of description does not accept any argument, + # strip arg before rendering + if ( + ctx_keys[0].startswith("interface ") + and line + and line.startswith("description ") + ): + lines_to_del.remove((ctx_keys, line)) + lines_to_del.insert(index, (ctx_keys, "description")) + # If there is a change in the segment routing block ranges, do it # in-place, to avoid requesting spurious label chunks which might fail if line and "segment-routing global-block" in line: - for (add_key, add_line) in lines_to_add: + for add_key, add_line in lines_to_add: if ( ctx_keys[0] == add_key[0] and add_line @@ -1124,7 +1131,6 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): continue if ctx_keys[0].startswith("router bgp") and line: - if line.startswith("neighbor "): # BGP changed how it displays swpX peers that are part of peer-group. Older # versions of frr would display these on separate lines: @@ -1206,7 +1212,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): bfd_nbr = "neighbor %s" % nbr bfd_search_string = bfd_nbr + r" bfd (\S+) (\S+) (\S+)" - for (ctx_keys, add_line) in lines_to_add: + for ctx_keys, add_line in lines_to_add: if ctx_keys[0].startswith("router bgp"): re_add_nbr_bfd_timers = re.search( bfd_search_string, add_line @@ -1236,7 +1242,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): dir = re_nbr_rm.group(3) search = "neighbor%sroute-map(.*)%s" % (neighbor_name, dir) save_line = "EMPTY" - for (ctx_keys_al, add_line) in lines_to_add: + for ctx_keys_al, add_line in lines_to_add: if ctx_keys_al[0].startswith("router bgp"): if add_line: rm_match = re.search(search, add_line) @@ -1256,7 +1262,7 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): lines_to_del_to_del.append((ctx_keys_al, line)) if adjust_for_bgp_node == 1: - for (ctx_keys_dl, dl_line) in lines_to_del: + for ctx_keys_dl, dl_line in lines_to_del: if ( ctx_keys_dl[0].startswith("router bgp") and len(ctx_keys_dl) > 1 @@ -1438,7 +1444,6 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): and ctx_keys[1] == "address-family l2vpn evpn" and ctx_keys[2].startswith("vni") ): - re_route_target = ( re.search("^route-target import (.*)$", line) if line is not None @@ -1514,19 +1519,18 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): lines_to_del_to_del.append((ctx_keys, line)) lines_to_add_to_del.append((tmp_ctx_keys, line)) - for (ctx_keys, line) in lines_to_del_to_del: + for ctx_keys, line in lines_to_del_to_del: try: lines_to_del.remove((ctx_keys, line)) except ValueError: pass - for (ctx_keys, line) in lines_to_add_to_del: + for ctx_keys, line in lines_to_add_to_del: try: lines_to_add.remove((ctx_keys, line)) except ValueError: pass - return (lines_to_add, lines_to_del) @@ -1537,8 +1541,7 @@ def ignore_unconfigurable_lines(lines_to_add, lines_to_del): """ lines_to_del_to_del = [] - for (ctx_keys, line) in lines_to_del: - + for ctx_keys, line in lines_to_del: # The integrated-vtysh-config one is technically "no"able but if we did # so frr-reload would stop working so do not let the user shoot # themselves in the foot by removing this. @@ -1559,7 +1562,7 @@ def ignore_unconfigurable_lines(lines_to_add, lines_to_del): log.info('"%s" cannot be removed' % (ctx_keys[-1],)) lines_to_del_to_del.append((ctx_keys, line)) - for (ctx_keys, line) in lines_to_del_to_del: + for ctx_keys, line in lines_to_del_to_del: lines_to_del.remove((ctx_keys, line)) return (lines_to_add, lines_to_del) @@ -1584,8 +1587,7 @@ def compare_context_objects(newconf, running): # Find contexts that are in newconf but not in running # Find contexts that are in running but not in newconf - for (running_ctx_keys, running_ctx) in iteritems(running.contexts): - + for running_ctx_keys, running_ctx in iteritems(running.contexts): if running_ctx_keys in newconf.contexts: newconf_ctx = newconf.contexts[running_ctx_keys] @@ -1606,7 +1608,6 @@ def compare_context_objects(newconf, running): lines_to_del.append((running_ctx_keys, new_del_line)) if running_ctx_keys not in newconf.contexts: - # We check that the len is 1 here so that we only look at ('router bgp 10') # and not ('router bgp 10', 'address-family ipv4 unicast'). The # latter could cause a false delete_bgpd positive if ipv4 unicast is in @@ -1777,14 +1778,12 @@ def compare_context_objects(newconf, running): # Find the lines within each context to add # Find the lines within each context to del - for (newconf_ctx_keys, newconf_ctx) in iteritems(newconf.contexts): - + for newconf_ctx_keys, newconf_ctx in iteritems(newconf.contexts): if newconf_ctx_keys in running.contexts: running_ctx = running.contexts[newconf_ctx_keys] for line in newconf_ctx.lines: if line not in running_ctx.dlines: - # candidate paths can only be added after the policy and segment list, # so add them to a separate array that is going to be appended at the end if ( @@ -1802,10 +1801,8 @@ def compare_context_objects(newconf, running): if line not in newconf_ctx.dlines: lines_to_del.append((newconf_ctx_keys, line)) - for (newconf_ctx_keys, newconf_ctx) in iteritems(newconf.contexts): - + for newconf_ctx_keys, newconf_ctx in iteritems(newconf.contexts): if newconf_ctx_keys not in running.contexts: - # candidate paths can only be added after the policy and segment list, # so add them to a separate array that is going to be appended at the end if ( @@ -2040,7 +2037,6 @@ if __name__ == "__main__": reload_ok = False if args.test: - # Create a Config object from the running config running = Config(vtysh) @@ -2056,8 +2052,7 @@ if __name__ == "__main__": print("\nLines To Delete") print("===============") - for (ctx_keys, line) in lines_to_del: - + for ctx_keys, line in lines_to_del: if line == "!": continue @@ -2083,8 +2078,7 @@ if __name__ == "__main__": print("\nLines To Add") print("============") - for (ctx_keys, line) in lines_to_add: - + for ctx_keys, line in lines_to_add: if line == "!": continue @@ -2172,8 +2166,7 @@ if __name__ == "__main__": # apply to other scenarios as well where configuring FOO adds BAR # to the config. if lines_to_del and x == 0: - for (ctx_keys, line) in lines_to_del: - + for ctx_keys, line in lines_to_del: if line == "!": continue @@ -2203,12 +2196,11 @@ if __name__ == "__main__": vtysh(["configure"] + cmd, stdouts) except VtyshException: - # - Pull the last entry from cmd (this would be # 'no ip ospf authentication message-digest 1.1.1.1' in # our example above # - Split that last entry by whitespace and drop the last word - log.info("Failed to execute %s", " ".join(cmd)) + log.error("Failed to execute %s", " ".join(cmd)) last_arg = cmd[-1].split(" ") if len(last_arg) <= 2: @@ -2231,8 +2223,7 @@ if __name__ == "__main__": if lines_to_add: lines_to_configure = [] - for (ctx_keys, line) in lines_to_add: - + for ctx_keys, line in lines_to_add: if line == "!": continue diff --git a/tools/frr.in b/tools/frr.in index cd24a96..94c15d5 100755 --- a/tools/frr.in +++ b/tools/frr.in @@ -14,11 +14,11 @@ # PATH=/bin:/usr/bin:/sbin:/usr/sbin -D_PATH="@CFG_SBIN@" # /usr/lib/frr -C_PATH="@CFG_SYSCONF@" # /etc/frr -V_PATH="@CFG_STATE@" # /var/run/frr -B_PATH="@CFG_BIN@" -VTYSH="@vtysh_bin@" # /usr/bin/vtysh +D_PATH="@e_sbindir@" # /usr/lib/frr +C_PATH="@e_frr_sysconfdir@" # /etc/frr +V_PATH="@e_frr_runstatedir@" # /var/run/frr +B_PATH="@e_bindir@" +VTYSH="@e_vtysh_bin@" # /usr/bin/vtysh FRR_USER="@enable_user@" # frr FRR_GROUP="@enable_group@" # frr FRR_VTY_GROUP="@enable_vty_group@" # frrvty diff --git a/tools/frr.service.in b/tools/frr.service.in index 1e958dd..b52ee3f 100644 --- a/tools/frr.service.in +++ b/tools/frr.service.in @@ -17,10 +17,10 @@ WatchdogSec=60s RestartSec=5 Restart=always LimitNOFILE=1024 -PIDFile=@CFG_STATE@/watchfrr.pid -ExecStart=@CFG_SBIN@/frrinit.sh start -ExecStop=@CFG_SBIN@/frrinit.sh stop -ExecReload=@CFG_SBIN@/frrinit.sh reload +PIDFile=@e_frr_runstatedir@/watchfrr.pid +ExecStart=@e_sbindir@/frrinit.sh start +ExecStop=@e_sbindir@/frrinit.sh stop +ExecReload=@e_sbindir@/frrinit.sh reload [Install] WantedBy=multi-user.target diff --git a/tools/frr@.service.in b/tools/frr@.service.in index 85408a0..c8a2d3b 100644 --- a/tools/frr@.service.in +++ b/tools/frr@.service.in @@ -17,10 +17,10 @@ WatchdogSec=60s RestartSec=5 Restart=always LimitNOFILE=1024 -PIDFile=@CFG_STATE@/%I/watchfrr.pid -ExecStart=@CFG_SBIN@/frrinit.sh start %I -ExecStop=@CFG_SBIN@/frrinit.sh stop %I -ExecReload=@CFG_SBIN@/frrinit.sh reload %I +PIDFile=@e_frr_runstatedir@/%I/watchfrr.pid +ExecStart=@e_sbindir@/frrinit.sh start %I +ExecStop=@e_sbindir@/frrinit.sh stop %I +ExecReload=@e_sbindir@/frrinit.sh reload %I [Install] WantedBy=multi-user.target diff --git a/tools/frr_babeltrace.py b/tools/frr_babeltrace.py index 4d974ad..9832568 100755 --- a/tools/frr_babeltrace.py +++ b/tools/frr_babeltrace.py @@ -157,6 +157,46 @@ def parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv(event): parse_event(event, field_parsers) +def parse_frr_bgp_evpn_mh_es_evi_vtep_add(event): + """ + bgp evpn remote ead evi remote vtep add; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"esi": print_esi, + "vtep": print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_es_evi_vtep_del(event): + """ + bgp evpn remote ead evi remote vtep del; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"esi": print_esi, + "vtep": print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_ead_es_evi_route_upd(event): + """ + bgp evpn local ead evi vtep; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"esi": print_esi, + "vtep": print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_ead_es_evi_route_del(event): + """ + bgp evpn local ead evi vtep del; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + """ + field_parsers = {"esi": print_esi, + "vtep": print_net_ipv4_addr} + + parse_event(event, field_parsers) + def parse_frr_bgp_evpn_local_vni_add_zrecv(event): """ bgp evpn local-vni parser; raw format - @@ -205,6 +245,24 @@ def parse_frr_bgp_evpn_local_macip_del_zrecv(event): parse_event(event, field_parsers) +def parse_frr_bgp_evpn_advertise_type5(event): + """ + local originated type-5 route + """ + field_parsers = {"ip": print_ip_addr, + "rmac": print_mac, + "vtep": print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_withdraw_type5(event): + """ + local originated type-5 route withdraw + """ + field_parsers = {"ip": print_ip_addr} + + parse_event(event, field_parsers) + ############################ evpn parsers - end *############################# def main(): @@ -225,6 +283,14 @@ def main(): parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv, "frr_bgp:evpn_mh_local_es_evi_del_zrecv": parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv, + "frr_bgp:evpn_mh_es_evi_vtep_add": + parse_frr_bgp_evpn_mh_es_evi_vtep_add, + "frr_bgp:evpn_mh_es_evi_vtep_del": + parse_frr_bgp_evpn_mh_es_evi_vtep_del, + "frr_bgp:evpn_mh_local_ead_es_evi_route_upd": + parse_frr_bgp_evpn_mh_local_ead_es_evi_route_upd, + "frr_bgp:evpn_mh_local_ead_es_evi_route_del": + parse_frr_bgp_evpn_mh_local_ead_es_evi_route_del, "frr_bgp:evpn_local_vni_add_zrecv": parse_frr_bgp_evpn_local_vni_add_zrecv, "frr_bgp:evpn_local_l3vni_add_zrecv": @@ -233,6 +299,10 @@ def main(): parse_frr_bgp_evpn_local_macip_add_zrecv, "frr_bgp:evpn_local_macip_del_zrecv": parse_frr_bgp_evpn_local_macip_del_zrecv, + "frr_bgp:evpn_advertise_type5": + parse_frr_bgp_evpn_advertise_type5, + "frr_bgp:evpn_withdraw_type5": + parse_frr_bgp_evpn_withdraw_type5, } # get the trace path from the first command line argument diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in index 00b63a7..44d4195 100755 --- a/tools/frrcommon.sh.in +++ b/tools/frrcommon.sh.in @@ -14,18 +14,18 @@ # not perform any action. Note there is an "exit 1" if the main config # file does not exist. # -# This script should be installed in @CFG_SBIN@/frrcommon.sh +# This script should be installed in @e_sbindir@/frrcommon.sh # FRR_PATHSPACE is passed in from watchfrr suffix="${FRR_PATHSPACE:+/${FRR_PATHSPACE}}" nsopt="${FRR_PATHSPACE:+-N ${FRR_PATHSPACE}}" PATH=/bin:/usr/bin:/sbin:/usr/sbin -D_PATH="@CFG_SBIN@" # /usr/lib/frr -C_PATH="@CFG_SYSCONF@${suffix}" # /etc/frr -V_PATH="@CFG_STATE@${suffix}" # /var/run/frr -B_PATH="@CFG_BIN@" -VTYSH="@vtysh_bin@" # /usr/bin/vtysh +D_PATH="@e_sbindir@" # /usr/lib/frr +C_PATH="@e_frr_sysconfdir@${suffix}" # /etc/frr +V_PATH="@e_frr_runstatedir@${suffix}" # /var/run/frr +B_PATH="@e_bindir@" +VTYSH="@e_vtysh_bin@" # /usr/bin/vtysh FRR_USER="@enable_user@" # frr FRR_GROUP="@enable_group@" # frr FRR_VTY_GROUP="@enable_vty_group@" # frrvty diff --git a/tools/frrinit.sh.in b/tools/frrinit.sh.in index 428d57c..178d18d 100644 --- a/tools/frrinit.sh.in +++ b/tools/frrinit.sh.in @@ -37,7 +37,7 @@ self="`dirname $0`" if [ -r "$self/frrcommon.sh" ]; then . "$self/frrcommon.sh" else - . "@CFG_SBIN@/frrcommon.sh" + . "@e_sbindir@/frrcommon.sh" fi case "$1" in diff --git a/tools/gen_northbound_callbacks.c b/tools/gen_northbound_callbacks.c index 5b778a1..a879811 100644 --- a/tools/gen_northbound_callbacks.c +++ b/tools/gen_northbound_callbacks.c @@ -7,6 +7,7 @@ #define REALLY_NEED_PLAIN_GETOPT 1 #include +#include #include @@ -25,67 +26,70 @@ static void __attribute__((noreturn)) usage(int status) static struct nb_callback_info { int operation; bool optional; + bool need_config_write; char return_type[32]; char return_value[32]; char arguments[128]; } nb_callbacks[] = { { - .operation = NB_OP_CREATE, + .operation = NB_CB_CREATE, + .need_config_write = true, .return_type = "int ", .return_value = "NB_OK", .arguments = "struct nb_cb_create_args *args", }, { - .operation = NB_OP_MODIFY, + .operation = NB_CB_MODIFY, + .need_config_write = true, .return_type = "int ", .return_value = "NB_OK", .arguments = "struct nb_cb_modify_args *args", }, { - .operation = NB_OP_DESTROY, + .operation = NB_CB_DESTROY, .return_type = "int ", .return_value = "NB_OK", .arguments = "struct nb_cb_destroy_args *args", }, { - .operation = NB_OP_MOVE, + .operation = NB_CB_MOVE, .return_type = "int ", .return_value = "NB_OK", .arguments = "struct nb_cb_move_args *args", }, { - .operation = NB_OP_APPLY_FINISH, + .operation = NB_CB_APPLY_FINISH, .optional = true, .return_type = "void ", .return_value = "", .arguments = "struct nb_cb_apply_finish_args *args", }, { - .operation = NB_OP_GET_ELEM, + .operation = NB_CB_GET_ELEM, .return_type = "struct yang_data *", .return_value = "NULL", .arguments = "struct nb_cb_get_elem_args *args", }, { - .operation = NB_OP_GET_NEXT, + .operation = NB_CB_GET_NEXT, .return_type = "const void *", .return_value = "NULL", .arguments = "struct nb_cb_get_next_args *args", }, { - .operation = NB_OP_GET_KEYS, + .operation = NB_CB_GET_KEYS, .return_type = "int ", .return_value = "NB_OK", .arguments = "struct nb_cb_get_keys_args *args", }, { - .operation = NB_OP_LOOKUP_ENTRY, + .operation = NB_CB_LOOKUP_ENTRY, .return_type = "const void *", .return_value = "NULL", .arguments = "struct nb_cb_lookup_entry_args *args", }, { - .operation = NB_OP_RPC, + .operation = NB_CB_RPC, .return_type = "int ", .return_value = "NB_OK", .arguments = "struct nb_cb_rpc_args *args", @@ -96,6 +100,16 @@ static struct nb_callback_info { }, }; +/* + * Special-purpose info block for the cli-config-write callback. This + * is different enough from the config-oriented callbacks that it doesn't + * really fit in the array above. + */ +static struct nb_callback_info nb_config_write = { + .return_type = "void ", + .arguments = "struct vty *vty, const struct lyd_node *dnode, bool show_defaults", +}; + static void replace_hyphens_by_underscores(char *str) { char *p; @@ -106,7 +120,7 @@ static void replace_hyphens_by_underscores(char *str) } static void generate_callback_name(const struct lysc_node *snode, - enum nb_operation operation, char *buffer, + enum nb_cb_operation operation, char *buffer, size_t size) { struct list *snodes; @@ -128,7 +142,38 @@ static void generate_callback_name(const struct lysc_node *snode, strlcat(buffer, snode->name, size); strlcat(buffer, "_", size); } - strlcat(buffer, nb_operation_name(operation), size); + strlcat(buffer, nb_cb_operation_name(operation), size); + list_delete(&snodes); + + replace_hyphens_by_underscores(buffer); +} + +static void generate_config_write_cb_name(const struct lysc_node *snode, + char *buffer, size_t size) +{ + struct list *snodes; + struct listnode *ln; + + buffer[0] = '\0'; + + snodes = list_new(); + for (; snode; snode = snode->parent) { + /* Skip schema-only snodes. */ + if (CHECK_FLAG(snode->nodetype, LYS_USES | LYS_CHOICE | LYS_CASE + | LYS_INPUT + | LYS_OUTPUT)) + continue; + + listnode_add_head(snodes, (void *)snode); + } + + for (ALL_LIST_ELEMENTS_RO(snodes, ln, snode)) { + strlcat(buffer, snode->name, size); + strlcat(buffer, "_", size); + } + + strlcat(buffer, "cli_write", size); + list_delete(&snodes); replace_hyphens_by_underscores(buffer); @@ -140,8 +185,16 @@ static void generate_prototype(const struct nb_callback_info *ncinfo, printf("%s%s(%s);\n", ncinfo->return_type, cb_name, ncinfo->arguments); } +static void generate_config_write_prototype(const struct nb_callback_info *ncinfo, + const char *cb_name) +{ + printf("%s%s(%s);\n", ncinfo->return_type, cb_name, ncinfo->arguments); +} + static int generate_prototypes(const struct lysc_node *snode, void *arg) { + bool need_config_write = true; + switch (snode->nodetype) { case LYS_CONTAINER: case LYS_LEAF: @@ -159,12 +212,21 @@ static int generate_prototypes(const struct lysc_node *snode, void *arg) char cb_name[BUFSIZ]; if (cb->optional - || !nb_operation_is_valid(cb->operation, snode)) + || !nb_cb_operation_is_valid(cb->operation, snode)) continue; generate_callback_name(snode, cb->operation, cb_name, sizeof(cb_name)); generate_prototype(cb, cb_name); + + if (cb->need_config_write && need_config_write) { + generate_config_write_cb_name(snode, cb_name, + sizeof(cb_name)); + generate_config_write_prototype(&nb_config_write, + cb_name); + + need_config_write = false; + } } return YANG_ITER_CONTINUE; @@ -177,10 +239,10 @@ static void generate_callback(const struct nb_callback_info *ncinfo, ncinfo->return_type, cb_name, ncinfo->arguments); switch (ncinfo->operation) { - case NB_OP_CREATE: - case NB_OP_MODIFY: - case NB_OP_DESTROY: - case NB_OP_MOVE: + case NB_CB_CREATE: + case NB_CB_MODIFY: + case NB_CB_DESTROY: + case NB_CB_MOVE: printf("\tswitch (args->event) {\n" "\tcase NB_EV_VALIDATE:\n" "\tcase NB_EV_PREPARE:\n" @@ -200,9 +262,22 @@ static void generate_callback(const struct nb_callback_info *ncinfo, printf("\treturn %s;\n}\n\n", ncinfo->return_value); } +static void generate_config_write_callback(const struct nb_callback_info *ncinfo, + const char *cb_name) +{ + printf("%s%s%s(%s)\n{\n", static_cbs ? "static " : "", + ncinfo->return_type, cb_name, ncinfo->arguments); + + /* Add a comment, since these callbacks may not all be needed. */ + printf("\t/* TODO: this cli callback is optional; the cli output may not need to be done at each node. */\n"); + + printf("}\n\n"); +} + static int generate_callbacks(const struct lysc_node *snode, void *arg) { bool first = true; + bool need_config_write = true; switch (snode->nodetype) { case LYS_CONTAINER: @@ -221,7 +296,7 @@ static int generate_callbacks(const struct lysc_node *snode, void *arg) char cb_name[BUFSIZ]; if (cb->optional - || !nb_operation_is_valid(cb->operation, snode)) + || !nb_cb_operation_is_valid(cb->operation, snode)) continue; if (first) { @@ -240,6 +315,15 @@ static int generate_callbacks(const struct lysc_node *snode, void *arg) generate_callback_name(snode, cb->operation, cb_name, sizeof(cb_name)); generate_callback(cb, cb_name); + + if (cb->need_config_write && need_config_write) { + generate_config_write_cb_name(snode, cb_name, + sizeof(cb_name)); + generate_config_write_callback(&nb_config_write, + cb_name); + + need_config_write = false; + } } return YANG_ITER_CONTINUE; @@ -248,6 +332,10 @@ static int generate_callbacks(const struct lysc_node *snode, void *arg) static int generate_nb_nodes(const struct lysc_node *snode, void *arg) { bool first = true; + char cb_name[BUFSIZ]; + char xpath[XPATH_MAXLEN]; + bool config_pass = *(bool *)arg; + bool need_config_write = true; switch (snode->nodetype) { case LYS_CONTAINER: @@ -261,31 +349,53 @@ static int generate_nb_nodes(const struct lysc_node *snode, void *arg) return YANG_ITER_CONTINUE; } + /* We generate two types of structs currently; behavior is a little + * different between the types. + */ for (struct nb_callback_info *cb = &nb_callbacks[0]; cb->operation != -1; cb++) { - char cb_name[BUFSIZ]; if (cb->optional - || !nb_operation_is_valid(cb->operation, snode)) + || !nb_cb_operation_is_valid(cb->operation, snode)) continue; - if (first) { - char xpath[XPATH_MAXLEN]; + if (config_pass) { + if (first) { + yang_snode_get_path(snode, YANG_PATH_DATA, xpath, + sizeof(xpath)); - yang_snode_get_path(snode, YANG_PATH_DATA, xpath, - sizeof(xpath)); + printf("\t\t{\n" + "\t\t\t.xpath = \"%s\",\n", + xpath); + printf("\t\t\t.cbs = {\n"); + first = false; + } - printf("\t\t{\n" - "\t\t\t.xpath = \"%s\",\n", - xpath); - printf("\t\t\t.cbs = {\n"); - first = false; - } + generate_callback_name(snode, cb->operation, cb_name, + sizeof(cb_name)); + printf("\t\t\t\t.%s = %s,\n", + nb_cb_operation_name(cb->operation), + cb_name); + } else if (cb->need_config_write && need_config_write) { + if (first) { + yang_snode_get_path(snode, + YANG_PATH_DATA, + xpath, + sizeof(xpath)); + + printf("\t\t{\n" + "\t\t\t.xpath = \"%s\",\n", + xpath); + printf("\t\t\t.cbs = {\n"); + first = false; + } - generate_callback_name(snode, cb->operation, cb_name, - sizeof(cb_name)); - printf("\t\t\t\t.%s = %s,\n", nb_operation_name(cb->operation), - cb_name); + generate_config_write_cb_name(snode, cb_name, + sizeof(cb_name)); + printf("\t\t\t\t.cli_show = %s,\n", cb_name); + + need_config_write = false; + } } if (!first) { @@ -303,6 +413,7 @@ int main(int argc, char *argv[]) char module_name_underscores[64]; struct stat st; int opt; + bool config_pass; while ((opt = getopt(argc, argv, "hp:s")) != -1) { switch (opt) { @@ -348,13 +459,18 @@ int main(int argc, char *argv[]) module = yang_module_find(argv[0]); if (!module) /* Non-native FRR module (e.g. modules from unit tests). */ - module = yang_module_load(argv[0]); + module = yang_module_load(argv[0], NULL); yang_init_loading_complete(); /* Create a nb_node for all YANG schema nodes. */ nb_nodes_create(); + /* Emit bare-bones license line (and fool the checkpatch regex + * that triggers a warning). + */ + printf("// SPDX-" "License-Identifier: GPL-2.0-or-later\n\n"); + /* Generate callback prototypes. */ if (!static_cbs) { printf("/* prototypes */\n"); @@ -369,13 +485,38 @@ int main(int argc, char *argv[]) sizeof(module_name_underscores)); replace_hyphens_by_underscores(module_name_underscores); - /* Generate frr_yang_module_info array. */ + /* + * We're going to generate two structs here, two arrays of callbacks: + * first one with config-handling callbacks, then a second struct with + * config-output-oriented callbacks. + */ + + /* Generate frr_yang_module_info array, with config-handling callbacks */ + config_pass = true; printf("/* clang-format off */\n" - "const struct frr_yang_module_info %s_info = {\n" + "const struct frr_yang_module_info %s_nb_info = {\n" "\t.name = \"%s\",\n" "\t.nodes = {\n", module_name_underscores, module->name); - yang_snodes_iterate(module->info, generate_nb_nodes, 0, NULL); + yang_snodes_iterate(module->info, generate_nb_nodes, 0, &config_pass); + + /* Emit terminator element */ + printf("\t\t{\n" + "\t\t\t.xpath = NULL,\n" + "\t\t},\n"); + printf("\t}\n" + "};\n"); + + /* Generate second array, with output-oriented callbacks. */ + config_pass = false; + printf("\n/* clang-format off */\n" + "const struct frr_yang_module_info %s_cli_info = {\n" + "\t.name = \"%s\",\n" + "\t.nodes = {\n", + module_name_underscores, module->name); + yang_snodes_iterate(module->info, generate_nb_nodes, 0, &config_pass); + + /* Emit terminator element */ printf("\t\t{\n" "\t\t\t.xpath = NULL,\n" "\t\t},\n"); diff --git a/tools/gen_yang_deviations.c b/tools/gen_yang_deviations.c index fc9f55b..251643c 100644 --- a/tools/gen_yang_deviations.c +++ b/tools/gen_yang_deviations.c @@ -55,7 +55,7 @@ int main(int argc, char *argv[]) yang_init(false, false); /* Load YANG module. */ - module = yang_module_load(argv[0]); + module = yang_module_load(argv[0], NULL); /* Generate deviations. */ yang_snodes_iterate(module->info, generate_yang_deviation, 0, NULL); diff --git a/tools/valgrind.supp b/tools/valgrind.supp index da3d4a8..d2cb411 100644 --- a/tools/valgrind.supp +++ b/tools/valgrind.supp @@ -23,6 +23,15 @@ fun:cap_init fun:zprivs_caps_init } +{ + + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:getgrouplist + fun:zprivs_init + fun:frr_init +} { Memcheck:Leak diff --git a/tools/watchfrr.sh.in b/tools/watchfrr.sh.in index 712f962..31279f6 100644 --- a/tools/watchfrr.sh.in +++ b/tools/watchfrr.sh.in @@ -5,7 +5,7 @@ # internally by watchfrr to start the protocol daemons with the appropriate # options. # -# This script should be installed in @CFG_SBIN@/watchfrr.sh +# This script should be installed in @e_sbindir@/watchfrr.sh log_success_msg() { : @@ -27,7 +27,7 @@ self="`dirname $0`" if [ -r "$self/frrcommon.sh" ]; then . "$self/frrcommon.sh" else - . "@CFG_SBIN@/frrcommon.sh" + . "@e_sbindir@/frrcommon.sh" fi frrcommon_main "$@" -- cgit v1.2.3