-CF_ADDTO(dynamic_attr, BGP_ORIGIN
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_ENUM_BGP_ORIGIN, EA_CODE(EAP_BGP, BA_ORIGIN)); })
-CF_ADDTO(dynamic_attr, BGP_PATH
- { $$ = f_new_dynamic_attr(EAF_TYPE_AS_PATH, T_PATH, EA_CODE(EAP_BGP, BA_AS_PATH)); })
-CF_ADDTO(dynamic_attr, BGP_NEXT_HOP
- { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_CODE(EAP_BGP, BA_NEXT_HOP)); })
-CF_ADDTO(dynamic_attr, BGP_MED
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC)); })
-CF_ADDTO(dynamic_attr, BGP_LOCAL_PREF
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(EAP_BGP, BA_LOCAL_PREF)); })
-CF_ADDTO(dynamic_attr, BGP_ATOMIC_AGGR
- { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(EAP_BGP, BA_ATOMIC_AGGR)); })
-CF_ADDTO(dynamic_attr, BGP_AGGREGATOR
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(EAP_BGP, BA_AGGREGATOR)); })
-CF_ADDTO(dynamic_attr, BGP_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_COMMUNITY)); })
-CF_ADDTO(dynamic_attr, BGP_ORIGINATOR_ID
- { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_CODE(EAP_BGP, BA_ORIGINATOR_ID)); })
-CF_ADDTO(dynamic_attr, BGP_CLUSTER_LIST
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); })
-CF_ADDTO(dynamic_attr, BGP_EXT_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(EAP_BGP, BA_EXT_COMMUNITY)); })
+bgp_channel_start: bgp_afi
+{
+ const struct bgp_af_desc *desc = bgp_get_af_desc($1);
+
+ if (!desc)
+ cf_error("Unknown AFI/SAFI");
+
+ this_channel = channel_config_get(&channel_bgp, desc->name, desc->net, this_proto);
+
+ /* New channel */
+ if (!BGP_CC->desc)
+ {
+ BGP_CC->c.in_filter = FILTER_UNDEF;
+ BGP_CC->c.out_filter = FILTER_UNDEF;
+ BGP_CC->c.ra_mode = RA_UNDEF;
+ BGP_CC->afi = $1;
+ BGP_CC->desc = desc;
+ BGP_CC->next_hop_keep = 0xff; /* undefined */
+ BGP_CC->gr_able = 0xff; /* undefined */
+ BGP_CC->llgr_able = 0xff; /* undefined */
+ BGP_CC->llgr_time = ~0U; /* undefined */
+ }
+};
+
+bgp_nh:
+ bool { $$ = $1; }
+ | IBGP { $$ = NH_IBGP; }
+ | EBGP { $$ = NH_EBGP; }
+
+bgp_channel_item:
+ channel_item
+ | NEXT HOP ADDRESS ipa { BGP_CC->next_hop_addr = $4; }
+ | NEXT HOP SELF bgp_nh { BGP_CC->next_hop_self = $4; }
+ | NEXT HOP KEEP bgp_nh { BGP_CC->next_hop_keep = $4; }
+ | MISSING LLADDR SELF { BGP_CC->missing_lladdr = MLL_SELF; }
+ | MISSING LLADDR DROP { BGP_CC->missing_lladdr = MLL_DROP; }
+ | MISSING LLADDR IGNORE { BGP_CC->missing_lladdr = MLL_IGNORE; }
+ | GATEWAY DIRECT { BGP_CC->gw_mode = GW_DIRECT; }
+ | GATEWAY RECURSIVE { BGP_CC->gw_mode = GW_RECURSIVE; }
+ | SECONDARY bool { BGP_CC->secondary = $2; }
+ | GRACEFUL RESTART bool { BGP_CC->gr_able = $3; }
+ | LONG LIVED GRACEFUL RESTART bool { BGP_CC->llgr_able = $5; }
+ | LONG LIVED STALE TIME expr { BGP_CC->llgr_time = $5; }
+ | EXTENDED NEXT HOP bool { BGP_CC->ext_next_hop = $4; }
+ | ADD PATHS RX { BGP_CC->add_path = BGP_ADD_PATH_RX; }
+ | ADD PATHS TX { BGP_CC->add_path = BGP_ADD_PATH_TX; }
+ | ADD PATHS bool { BGP_CC->add_path = $3 ? BGP_ADD_PATH_FULL : 0; }
+ | IMPORT TABLE bool { BGP_CC->import_table = $3; }
+ | IGP TABLE rtable {
+ if (BGP_CC->desc->no_igp)
+ cf_error("IGP table not allowed here");
+
+ if ($3->addr_type == NET_IP4)
+ BGP_CC->igp_table_ip4 = $3;
+ else if ($3->addr_type == NET_IP6)
+ BGP_CC->igp_table_ip6 = $3;
+ else
+ cf_error("Mismatched IGP table type");
+ }
+ ;
+
+bgp_channel_opts:
+ /* empty */
+ | bgp_channel_opts bgp_channel_item ';'
+ ;
+
+bgp_channel_opt_list:
+ /* empty */
+ | '{' bgp_channel_opts '}'
+ ;
+
+bgp_channel_end:
+{
+ if (!this_channel->table)
+ cf_error("Routing table not specified");
+
+ this_channel = NULL;
+};
+
+bgp_proto_channel: bgp_channel_start bgp_channel_opt_list bgp_channel_end;
+
+
+dynamic_attr: BGP_ORIGIN
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_ENUM_BGP_ORIGIN, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); } ;
+dynamic_attr: BGP_PATH
+ { $$ = f_new_dynamic_attr(EAF_TYPE_AS_PATH, T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); } ;
+dynamic_attr: BGP_NEXT_HOP
+ { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_CODE(PROTOCOL_BGP, BA_NEXT_HOP)); } ;
+dynamic_attr: BGP_MED
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); } ;
+dynamic_attr: BGP_LOCAL_PREF
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); } ;
+dynamic_attr: BGP_ATOMIC_AGGR
+ { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(PROTOCOL_BGP, BA_ATOMIC_AGGR)); } ;
+dynamic_attr: BGP_AGGREGATOR
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_AGGREGATOR)); } ;
+dynamic_attr: BGP_COMMUNITY
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); } ;
+dynamic_attr: BGP_ORIGINATOR_ID
+ { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID)); } ;
+dynamic_attr: BGP_CLUSTER_LIST
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST)); } ;
+dynamic_attr: BGP_EXT_COMMUNITY
+ { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(PROTOCOL_BGP, BA_EXT_COMMUNITY)); } ;
+dynamic_attr: BGP_LARGE_COMMUNITY
+ { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(PROTOCOL_BGP, BA_LARGE_COMMUNITY)); } ;