]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #2574 from pacovn/Coverity_1399202_Copy-paste_error
authorRuss White <russ@riw.us>
Fri, 29 Jun 2018 22:35:12 +0000 (18:35 -0400)
committerGitHub <noreply@github.com>
Fri, 29 Jun 2018 22:35:12 +0000 (18:35 -0400)
bgpd: copy-paste error (Coverity 1399202)

36 files changed:
bgpd/bgp_evpn.c
bgpd/bgp_evpn_vty.c
bgpd/bgp_flowspec.c
bgpd/bgp_flowspec_util.c
bgpd/bgp_flowspec_util.h
bgpd/bgp_flowspec_vty.c
bgpd/bgp_open.c
bgpd/bgp_pbr.c
bgpd/bgp_pbr.h
bgpd/bgp_route.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/rfapi/bgp_rfapi_cfg.c
bgpd/rfapi/rfapi_vty.c
isisd/isis_lsp.c
isisd/isis_pfpacket.c
isisd/isis_spf.c
lib/linklist.c
lib/pbr.h
lib/stream.c
lib/stream.h
nhrpd/vici.c
ospf6d/ospf6_abr.c
ospf6d/ospf6_asbr.c
ospf6d/ospf6_intra.c
ospf6d/ospf6_proto.c
ospf6d/ospf6_proto.h
pimd/pim_zebra.c
vtysh/vtysh.c
zebra/kernel_netlink.c
zebra/zapi_msg.c
zebra/zebra_netns_id.c
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zebra_rib.c
zebra/zserv.c

index 0557bbcce9a59efd3e55a2ad9037f4b1426e49b5..959418658c9587ae8be1afcb8bcbd0ac9a1992ef 100644 (file)
@@ -4242,8 +4242,9 @@ void bgp_evpn_unconfigure_import_rt_for_vrf(struct bgp *bgp_vrf,
        if (node_to_del)
                list_delete_node(bgp_vrf->vrf_import_rtl, node_to_del);
 
+       assert(bgp_vrf->vrf_import_rtl);
        /* fallback to auto import rt, if this was the last RT */
-       if (list_isempty(bgp_vrf->vrf_import_rtl)) {
+       if (bgp_vrf->vrf_import_rtl && list_isempty(bgp_vrf->vrf_import_rtl)) {
                UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD);
                evpn_auto_rt_import_add_for_vrf(bgp_vrf);
        }
index cb71e06149ebd2f3323d41f43898fc5426aeda94..5a4ebc9b173529f48279ae1a68b986b653841828 100644 (file)
@@ -52,7 +52,6 @@ struct vni_walk_ctx {
        json_object *json;
 };
 
-#if defined(HAVE_CUMULUS)
 static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
                                  json_object *json)
 {
@@ -245,7 +244,7 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt,
        for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
                if (json)
                        json_object_array_add(
-                               json_vnis, json_object_new_int64(tmp_vpn->vni));
+                               json_vnis, json_object_new_int(tmp_vpn->vni));
                else
                        vty_out(vty, "  %u\n", tmp_vpn->vni);
        }
@@ -980,7 +979,6 @@ static void show_vni_entry(struct hash_backet *backet, void *args[])
                vty_out(vty, "\n");
        }
 }
-#endif /* HAVE_CUMULUS */
 
 static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                 enum bgp_show_type type, void *output_arg,
@@ -1636,8 +1634,6 @@ DEFUN(no_evpnrt5_network,
                argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
 }
 
-#if defined(HAVE_CUMULUS)
-
 static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
 {
        evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl);
@@ -1721,6 +1717,7 @@ static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
                        list_delete_node(vpn->import_rtl, node_to_del);
        }
 
+       assert(vpn->import_rtl);
        /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
        if (list_isempty(vpn->import_rtl)) {
                UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
@@ -1788,6 +1785,7 @@ static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
                        list_delete_node(vpn->export_rtl, node_to_del);
        }
 
+       assert(vpn->export_rtl);
        if (list_isempty(vpn->export_rtl)) {
                UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
                bgp_evpn_derive_auto_rt_export(bgp, vpn);
@@ -2752,7 +2750,6 @@ static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
        bgp->advertise_autort_rfc8365 = 0;
        bgp_evpn_handle_autort_change(bgp);
 }
-#endif /* HAVE_CUMULUS */
 
 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
 {
@@ -2799,7 +2796,6 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
        }
 }
 
-#if defined(HAVE_CUMULUS)
 DEFUN (bgp_evpn_advertise_default_gw_vni,
        bgp_evpn_advertise_default_gw_vni_cmd,
        "advertise-default-gw",
@@ -3262,10 +3258,11 @@ DEFUN(show_bgp_l2vpn_evpn_es,
 {
        int idx = 0;
        uint8_t uj = 0;
-       esi_t esi = {0};
+       esi_t esi;
        json_object *json = NULL;
        struct bgp *bgp = NULL;
 
+       memset(&esi, 0, sizeof(esi));
        uj = use_json(argc, argv);
 
        bgp = bgp_get_default();
@@ -3547,10 +3544,11 @@ DEFUN(show_bgp_l2vpn_evpn_route_esi,
       JSON_STR)
 {
        int uj = 0;
-       esi_t esi = {0};
+       esi_t esi;
        struct bgp *bgp = NULL;
        json_object *json = NULL;
 
+       memset(&esi, 0, sizeof(esi));
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
@@ -3904,7 +3902,6 @@ DEFUN(show_bgp_l2vpn_evpn_import_rt,
        return CMD_SUCCESS;
 }
 
-#if defined(HAVE_CUMULUS)
 DEFUN(test_adv_evpn_type4_route,
       test_adv_evpn_type4_route_cmd,
       "advertise es ESI",
@@ -4064,7 +4061,6 @@ ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
             "show bgp evpn import-rt",
             SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
-#endif
 
 DEFUN_NOSH (bgp_evpn_vni,
             bgp_evpn_vni_cmd,
@@ -4841,7 +4837,6 @@ DEFUN (no_bgp_evpn_vni_rt_without_val,
                evpn_unconfigure_export_rt(bgp, vpn, NULL);
        return CMD_SUCCESS;
 }
-#endif
 
 static int vni_cmp(const void **a, const void **b)
 {
@@ -4961,7 +4956,6 @@ void bgp_ethernetvpn_init(void)
        install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
        install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
        install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
-#if defined(HAVE_CUMULUS)
        install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
        install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
        install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
@@ -5027,5 +5021,4 @@ void bgp_ethernetvpn_init(void)
        install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
        install_element(BGP_EVPN_VNI_NODE,
                        &no_bgp_evpn_advertise_vni_subnet_cmd);
-#endif
 }
index 884c5aa51a182aab9ae5360a027b7bb4b810ba63..9b998d4497f9031c81362ff3acdb98ffab103bf6 100644 (file)
@@ -59,7 +59,8 @@ static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len)
                                                   len - offset, NULL, &error);
                        break;
                case FLOWSPEC_TCP_FLAGS:
-                       ret = bgp_flowspec_tcpflags_decode(
+               case FLOWSPEC_FRAGMENT:
+                       ret = bgp_flowspec_bitmask_decode(
                                                   BGP_FLOWSPEC_VALIDATE_ONLY,
                                                   nlri_content + offset,
                                                   len - offset, NULL, &error);
@@ -71,12 +72,6 @@ static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len)
                                                nlri_content + offset,
                                                len - offset, NULL, &error);
                        break;
-               case FLOWSPEC_FRAGMENT:
-                       ret = bgp_flowspec_fragment_type_decode(
-                                               BGP_FLOWSPEC_VALIDATE_ONLY,
-                                               nlri_content + offset,
-                                               len - offset, NULL, &error);
-                       break;
                default:
                        error = -1;
                        break;
index 956cf28c211dfc2df74f0a0bada96ccaac4acad3..1b874276613c2a32150578c30a3a173761e2cbff 100644 (file)
@@ -124,8 +124,9 @@ static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
                                                     len - offset,
                                                     NULL, &error);
                        break;
+               case FLOWSPEC_FRAGMENT:
                case FLOWSPEC_TCP_FLAGS:
-                       ret = bgp_flowspec_tcpflags_decode(
+                       ret = bgp_flowspec_bitmask_decode(
                                                BGP_FLOWSPEC_VALIDATE_ONLY,
                                                nlri_content+offset,
                                                len - offset,
@@ -139,13 +140,6 @@ static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
                                                len - offset, NULL,
                                                &error);
                        break;
-               case FLOWSPEC_FRAGMENT:
-                       ret = bgp_flowspec_fragment_type_decode(
-                                               BGP_FLOWSPEC_VALIDATE_ONLY,
-                                               nlri_content + offset,
-                                               len - offset, NULL,
-                                               &error);
-                       break;
                default:
                        error = -1;
                        break;
@@ -312,14 +306,14 @@ int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
 
 
 /*
- * handle the flowspec tcpflags field
+ * handle the flowspec tcpflags or fragment field
  * return number of bytes analysed
  * if there is an error, the passed error param is used to give error:
  * -1 if decoding error,
  * if result is a string, its assumed length
  *  is BGP_FLOWSPEC_STRING_DISPLAY_MAX
  */
-int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
+int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
                                 uint8_t *nlri_ptr,
                                 uint32_t max_len,
                                 void *result, int *error)
@@ -348,32 +342,33 @@ int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
                case BGP_FLOWSPEC_RETURN_STRING:
                        if (op[1] == 1 && loop != 0) {
                                len_written = snprintf(ptr, len_string,
-                                                      ", and ");
+                                                      ",&");
                                len_string -= len_written;
                                ptr += len_written;
                        } else if (op[1] == 0 && loop != 0) {
                                len_written = snprintf(ptr, len_string,
-                                                     ", or ");
+                                                     ",|");
                                len_string -= len_written;
                                ptr += len_written;
                        }
-                       len_written = snprintf(ptr, len_string,
-                                              "tcp flags is ");
-                       len_string -= len_written;
-                       ptr += len_written;
-                       if (op[6] == 1) {
-                               ptr += snprintf(ptr, len_string,
-                                              "not ");
+                       if (op[7] == 1) {
+                               len_written = snprintf(ptr, len_string,
+                                              "= ");
+                               len_string -= len_written;
+                               ptr += len_written;
+                       } else {
+                               len_written = snprintf(ptr, len_string,
+                                                      "∋ ");
                                len_string -= len_written;
                                ptr += len_written;
                        }
-                       if (op[7] == 1) {
-                               ptr += snprintf(ptr, len_string,
-                                              "exactly match ");
+                       if (op[6] == 1) {
+                               len_written = snprintf(ptr, len_string,
+                                              "! ");
                                len_string -= len_written;
                                ptr += len_written;
                        }
-                       ptr += snprintf(ptr, len_string,
+                       len_written = snprintf(ptr, len_string,
                                       "%d", value);
                        len_string -= len_written;
                        ptr += len_written;
@@ -419,92 +414,6 @@ int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
        return offset;
 }
 
-/*
- * handle the flowspec fragment type field
- * return error (returned values are invalid) or number of bytes analysed
- * -1 if error in decoding
- * >= 0 : number of bytes analysed (ok).
- */
-int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
-                                     uint8_t *nlri_ptr,
-                                     uint32_t max_len,
-                                     void *result, int *error)
-{
-       int op[8];
-       int len, value, value_size, loop = 0;
-       char *ptr = (char *)result; /* for return_string */
-       struct bgp_pbr_fragment_val *mval =
-               (struct bgp_pbr_fragment_val *)result;
-       uint32_t offset = 0;
-       int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
-       int len_written;
-
-       *error = 0;
-       do {
-               hex2bin(&nlri_ptr[offset], op);
-               offset++;
-               len = 2 * op[2] + op[3];
-               value_size = 1 << len;
-               value = hexstr2num(&nlri_ptr[offset], value_size);
-               if (value != 1 && value != 2 && value != 4 && value != 8)
-                       *error = -1;
-               offset += value_size;
-               /* TODO : as per RFC5574 : first Fragment bits are Reserved
-                * does that mean that it is not possible
-                * to handle multiple occurences ?
-                * as of today, we only grab the first TCP fragment
-                */
-               if (loop) {
-                       *error = -2;
-                       loop++;
-                       continue;
-               }
-               switch (type) {
-               case BGP_FLOWSPEC_RETURN_STRING:
-                       switch (value) {
-                       case 1:
-                               len_written = snprintf(ptr, len_string,
-                                                      "dont-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       case 2:
-                               len_written = snprintf(ptr, len_string,
-                                                     "is-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       case 4:
-                               len_written = snprintf(ptr, len_string,
-                                                      "first-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       case 8:
-                               len_written = snprintf(ptr, len_string,
-                                                      "last-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       default:
-                               {}
-                       }
-                       break;
-               case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
-                       mval->bitmask = (uint8_t)value;
-                       break;
-               case BGP_FLOWSPEC_VALIDATE_ONLY:
-               default:
-                       /* no action */
-                       break;
-               }
-               loop++;
-       } while (op[0] == 0 && offset < max_len - 1);
-       if (offset > max_len)
-               *error = -1;
-       return offset;
-}
-
 int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                  struct bgp_pbr_entry_main *bpem)
 {
@@ -623,7 +532,7 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                                        &error);
                        break;
                case FLOWSPEC_TCP_FLAGS:
-                       ret = bgp_flowspec_tcpflags_decode(
+                       ret = bgp_flowspec_bitmask_decode(
                                        BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
                                        nlri_content + offset,
                                        len - offset,
@@ -637,7 +546,7 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                        offset += ret;
                        break;
                case FLOWSPEC_FRAGMENT:
-                       ret = bgp_flowspec_fragment_type_decode(
+                       ret = bgp_flowspec_bitmask_decode(
                                        BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
                                        nlri_content + offset,
                                        len - offset, &bpem->fragment,
@@ -646,7 +555,7 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                zlog_err("%s: flowspec_fragment_type_decode error %d",
                                         __func__, error);
                        else
-                               bpem->match_bitmask |= FRAGMENT_PRESENT;
+                               bpem->match_fragment_num = error;
                        offset += ret;
                        break;
                default:
index e4454ab4dba3fe87876ab40def2a74a8cf1abb98..2d16e57a36fdc9de6dd09fc2e5cb98797488687b 100644 (file)
@@ -41,15 +41,11 @@ extern int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
                                   uint32_t max_len,
                                   void *result, int *error);
 
-extern int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
+extern int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
                                        uint8_t *nlri_ptr,
                                        uint32_t max_len,
                                        void *result, int *error);
 
-extern int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
-                                            uint8_t *nlri_ptr,
-                                            uint32_t max_len,
-                                            void *result, int *error);
 struct bgp_pbr_entry_main;
 extern int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                         struct bgp_pbr_entry_main *bpem);
index b21e5ae0dcc4b2284c510c91dee3af34868d0d1c..90acd8fcb16f48beb0f07ac2436dae0eacd5c4d2 100644 (file)
@@ -62,7 +62,7 @@ static const struct message bgp_flowspec_display_min[] = {
        {FLOWSPEC_SRC_PORT, "srcp"},
        {FLOWSPEC_ICMP_TYPE, "type"},
        {FLOWSPEC_ICMP_CODE, "code"},
-       {FLOWSPEC_TCP_FLAGS, "flags"},
+       {FLOWSPEC_TCP_FLAGS, "tcp"},
        {FLOWSPEC_PKT_LEN, "pktlen"},
        {FLOWSPEC_DSCP, "dscp"},
        {FLOWSPEC_FRAGMENT, "pktfrag"},
@@ -173,7 +173,7 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
                        ptr += len_written;
                        break;
                case FLOWSPEC_TCP_FLAGS:
-                       ret = bgp_flowspec_tcpflags_decode(
+                       ret = bgp_flowspec_bitmask_decode(
                                              type_util,
                                              nlri_content+offset,
                                              len - offset,
@@ -221,11 +221,11 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
                        ptr += len_written;
                        break;
                case FLOWSPEC_FRAGMENT:
-                       ret = bgp_flowspec_fragment_type_decode(
-                                               type_util,
-                                               nlri_content + offset,
-                                               len - offset, local_string,
-                                               &error);
+                       ret = bgp_flowspec_bitmask_decode(
+                                             type_util,
+                                             nlri_content+offset,
+                                             len - offset,
+                                             local_string, &error);
                        if (ret <= 0)
                                break;
                        if (json_path) {
index aa98f8a55726423371b215cc2f7f34339537549f..da90bbd67dad6591b5747da3c1696948dee160ab 100644 (file)
@@ -80,8 +80,9 @@ void bgp_capability_vty_out(struct vty *vty, struct peer *peer,
                        afi_t afi;
                        safi_t safi;
 
-                       bgp_map_afi_safi_iana2int(ntohs(mpc.afi), mpc.safi,
-                                                 &afi, &safi);
+                       (void)bgp_map_afi_safi_iana2int(ntohs(mpc.afi),
+                                                       mpc.safi, &afi, &safi);
+
                        if (use_json) {
                                switch (afi) {
                                case AFI_IP:
index 5e36f9175048eb6d1a332ea8370ad0fd77576c65..45ec21631c0f2fcb6113ed1f273b52b4d4b614ef 100644 (file)
@@ -21,6 +21,7 @@
 #include "prefix.h"
 #include "zclient.h"
 #include "jhash.h"
+#include "pbr.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_pbr.h"
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_flowspec_private.h"
 
 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH_ENTRY, "PBR match entry")
 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH, "PBR match")
 DEFINE_MTYPE_STATIC(BGPD, PBR_ACTION, "PBR action")
 DEFINE_MTYPE_STATIC(BGPD, PBR, "BGP PBR Context")
+DEFINE_MTYPE_STATIC(BGPD, PBR_VALMASK, "BGP PBR Val Mask Value")
 
 RB_GENERATE(bgp_pbr_interface_head, bgp_pbr_interface,
            id_entry, bgp_pbr_interface_compare);
@@ -175,11 +178,220 @@ static int sprintf_bgp_pbr_match_val(char *str, struct bgp_pbr_match_val *mval,
                _cnt++; \
        } while (0)
 
+/* this structure can be used for port range,
+ * but also for other values range like packet length range
+ */
 struct bgp_pbr_range_port {
        uint16_t min_port;
        uint16_t max_port;
 };
 
+/* this structure can be used to filter with a mask
+ * for instance it supports not instructions like for
+ * tcpflags
+ */
+struct bgp_pbr_val_mask {
+       uint16_t val;
+       uint16_t mask;
+};
+
+/* this structure is used to pass instructs
+ * so that BGP can create pbr instructions to ZEBRA
+ */
+struct bgp_pbr_filter {
+       vrf_id_t vrf_id;
+       struct prefix *src;
+       struct prefix *dst;
+       uint8_t protocol;
+       struct bgp_pbr_range_port *pkt_len;
+       struct bgp_pbr_range_port *src_port;
+       struct bgp_pbr_range_port *dst_port;
+       struct bgp_pbr_val_mask *tcp_flags;
+       struct bgp_pbr_val_mask *dscp;
+       struct bgp_pbr_val_mask *pkt_len_val;
+       struct bgp_pbr_val_mask *fragment;
+};
+
+/* this structure is used to contain OR instructions
+ * so that BGP can create multiple pbr instructions
+ * to ZEBRA
+ */
+struct bgp_pbr_or_filter {
+       struct list *tcpflags;
+       struct list *dscp;
+       struct list *pkt_len;
+       struct list *fragment;
+       struct list *icmp_type;
+       struct list *icmp_code;
+};
+
+static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
+                                                 struct bgp_info *binfo,
+                                                 struct bgp_pbr_filter *bpf,
+                                                 struct nexthop *nh,
+                                                 float *rate);
+
+static bool bgp_pbr_extract_enumerate_unary_opposite(
+                                uint8_t unary_operator,
+                                struct bgp_pbr_val_mask *and_valmask,
+                                struct list *or_valmask, uint32_t value,
+                                uint8_t type_entry)
+{
+       if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
+               if (type_entry == FLOWSPEC_TCP_FLAGS) {
+                       and_valmask->mask |=
+                               TCP_HEADER_ALL_FLAGS &
+                               ~(value);
+               } else if (type_entry == FLOWSPEC_DSCP ||
+                          type_entry == FLOWSPEC_PKT_LEN ||
+                          type_entry == FLOWSPEC_FRAGMENT) {
+                       and_valmask->val = value;
+                       and_valmask->mask = 1; /* inverse */
+               }
+       } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
+               and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
+                                     sizeof(struct bgp_pbr_val_mask));
+               if (type_entry == FLOWSPEC_TCP_FLAGS) {
+                       and_valmask->val = TCP_HEADER_ALL_FLAGS;
+                       and_valmask->mask |=
+                               TCP_HEADER_ALL_FLAGS &
+                               ~(value);
+               } else if (type_entry == FLOWSPEC_DSCP ||
+                          type_entry == FLOWSPEC_FRAGMENT ||
+                          type_entry == FLOWSPEC_PKT_LEN) {
+                       and_valmask->val = value;
+                       and_valmask->mask = 1; /* inverse */
+               }
+               listnode_add(or_valmask, and_valmask);
+       } else if (type_entry == FLOWSPEC_ICMP_CODE ||
+                  type_entry == FLOWSPEC_ICMP_TYPE)
+               return false;
+       return true;
+}
+
+/* TCP : FIN and SYN -> val = ALL; mask = 3
+ * TCP : not (FIN and SYN) -> val = ALL; mask = ALL & ~(FIN|RST)
+ * other variables type: dscp, pkt len, fragment
+ * - value is copied in bgp_pbr_val_mask->val value
+ * - if negate form is identifierd, bgp_pbr_val_mask->mask set to 1
+ */
+static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
+                                           int num, uint8_t unary_operator,
+                                           void *valmask, uint8_t type_entry)
+{
+       int i = 0;
+       struct bgp_pbr_val_mask *and_valmask = NULL;
+       struct list *or_valmask = NULL;
+       bool ret;
+
+       if (valmask) {
+               if (unary_operator == OPERATOR_UNARY_AND) {
+                       and_valmask = (struct bgp_pbr_val_mask *)valmask;
+                       memset(and_valmask, 0, sizeof(struct bgp_pbr_val_mask));
+               } else if (unary_operator == OPERATOR_UNARY_OR) {
+                       or_valmask = (struct list *)valmask;
+               }
+       }
+       for (i = 0; i < num; i++) {
+               if (i != 0 && list[i].unary_operator !=
+                   unary_operator)
+                       return false;
+               if (!(list[i].compare_operator &
+                   OPERATOR_COMPARE_EQUAL_TO) &&
+                   !(list[i].compare_operator &
+                     OPERATOR_COMPARE_EXACT_MATCH)) {
+                       if ((list[i].compare_operator &
+                            OPERATOR_COMPARE_LESS_THAN) &&
+                           (list[i].compare_operator &
+                            OPERATOR_COMPARE_GREATER_THAN)) {
+                               ret = bgp_pbr_extract_enumerate_unary_opposite(
+                                                unary_operator, and_valmask,
+                                                or_valmask, list[i].value,
+                                                type_entry);
+                               if (ret == false)
+                                       return ret;
+                               continue;
+                       }
+                       return false;
+               }
+               if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
+                       if (type_entry == FLOWSPEC_TCP_FLAGS)
+                               and_valmask->mask |=
+                                       TCP_HEADER_ALL_FLAGS & list[i].value;
+               } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
+                       and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
+                                             sizeof(struct bgp_pbr_val_mask));
+                       if (type_entry == FLOWSPEC_TCP_FLAGS) {
+                               and_valmask->val = TCP_HEADER_ALL_FLAGS;
+                               and_valmask->mask |=
+                                       TCP_HEADER_ALL_FLAGS & list[i].value;
+                       } else if (type_entry == FLOWSPEC_DSCP ||
+                                  type_entry == FLOWSPEC_ICMP_TYPE ||
+                                  type_entry == FLOWSPEC_ICMP_CODE ||
+                                  type_entry == FLOWSPEC_FRAGMENT ||
+                                  type_entry == FLOWSPEC_PKT_LEN)
+                               and_valmask->val = list[i].value;
+                       listnode_add(or_valmask, and_valmask);
+               }
+       }
+       if (unary_operator == OPERATOR_UNARY_AND && and_valmask
+           && type_entry == FLOWSPEC_TCP_FLAGS)
+               and_valmask->val = TCP_HEADER_ALL_FLAGS;
+       return true;
+}
+
+/* if unary operator can either be UNARY_OR/AND/OR-AND.
+ * in the latter case, combinationf of both is not handled
+ */
+static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
+                                     int num, uint8_t unary_operator,
+                                     void *valmask, uint8_t type_entry)
+{
+       bool ret;
+       uint8_t unary_operator_val = unary_operator;
+       bool double_check = false;
+
+       if ((unary_operator & OPERATOR_UNARY_OR) &&
+           (unary_operator & OPERATOR_UNARY_AND)) {
+               unary_operator_val = OPERATOR_UNARY_AND;
+               double_check = true;
+       } else
+               unary_operator_val = unary_operator;
+       ret = bgp_pbr_extract_enumerate_unary(list, num, unary_operator_val,
+                                             valmask, type_entry);
+       if (!ret && double_check)
+               ret = bgp_pbr_extract_enumerate_unary(list, num,
+                                                     OPERATOR_UNARY_OR,
+                                                     valmask,
+                                                     type_entry);
+       return ret;
+}
+
+/* returns the unary operator that is in the list
+ * return 0 if both operators are used
+ */
+static uint8_t bgp_pbr_match_val_get_operator(struct bgp_pbr_match_val list[],
+                                             int num)
+
+{
+       int i;
+       uint8_t unary_operator = OPERATOR_UNARY_AND;
+
+       for (i = 0; i < num; i++) {
+               if (i == 0)
+                       continue;
+               if (list[i].unary_operator & OPERATOR_UNARY_OR)
+                       unary_operator = OPERATOR_UNARY_OR;
+               if ((list[i].unary_operator & OPERATOR_UNARY_AND
+                    && unary_operator == OPERATOR_UNARY_OR) ||
+                   (list[i].unary_operator & OPERATOR_UNARY_OR
+                    && unary_operator == OPERATOR_UNARY_AND))
+                       return 0;
+       }
+       return unary_operator;
+}
+
+
 /* return true if extraction ok
  */
 static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
@@ -231,6 +443,8 @@ static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
 
 static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
 {
+       bool enumerate_icmp = false;
+
        /* because bgp pbr entry may contain unsupported
         * combinations, a message will be displayed here if
         * not supported.
@@ -240,16 +454,6 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
         * - combination src/dst => drop
         * - combination srcport + @IP
         */
-       if (api->match_icmp_type_num || api->match_packet_length_num
-           || api->match_dscp_num || api->match_tcpflags_num) {
-               if (BGP_DEBUG(pbr, PBR)) {
-                       bgp_pbr_print_policy_route(api);
-                       zlog_debug("BGP: some SET actions not supported by Zebra. ignoring.");
-                       zlog_debug("BGP: case icmp or length or dscp or tcp flags");
-               }
-               return 0;
-       }
-
        if (api->match_protocol_num > 1) {
                if (BGP_DEBUG(pbr, PBR))
                        zlog_debug("BGP: match protocol operations:"
@@ -259,6 +463,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
        }
        if (api->match_protocol_num == 1 &&
            api->protocol[0].value != PROTOCOL_UDP &&
+           api->protocol[0].value != PROTOCOL_ICMP &&
            api->protocol[0].value != PROTOCOL_TCP) {
                if (BGP_DEBUG(pbr, PBR))
                        zlog_debug("BGP: match protocol operations:"
@@ -278,12 +483,114 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
                                   "too complex. ignoring.");
                return 0;
        }
+       if (!bgp_pbr_extract_enumerate(api->tcpflags,
+                                      api->match_tcpflags_num,
+                                      OPERATOR_UNARY_AND |
+                                      OPERATOR_UNARY_OR, NULL,
+                                      FLOWSPEC_TCP_FLAGS)) {
+               if (BGP_DEBUG(pbr, PBR))
+                       zlog_debug("BGP: match tcp flags:"
+                                  "too complex. ignoring.");
+               return 0;
+       }
+       if (!bgp_pbr_extract(api->icmp_type, api->match_icmp_type_num, NULL)) {
+               if (!bgp_pbr_extract_enumerate(api->icmp_type,
+                                              api->match_icmp_type_num,
+                                              OPERATOR_UNARY_OR, NULL,
+                                              FLOWSPEC_ICMP_TYPE)) {
+                       if (BGP_DEBUG(pbr, PBR))
+                               zlog_debug("BGP: match icmp type operations:"
+                                          "too complex. ignoring.");
+                       return 0;
+               }
+               enumerate_icmp = true;
+       }
+       if (!bgp_pbr_extract(api->icmp_code, api->match_icmp_code_num, NULL)) {
+               if (!bgp_pbr_extract_enumerate(api->icmp_code,
+                                              api->match_icmp_code_num,
+                                              OPERATOR_UNARY_OR, NULL,
+                                              FLOWSPEC_ICMP_CODE)) {
+                       if (BGP_DEBUG(pbr, PBR))
+                               zlog_debug("BGP: match icmp code operations:"
+                                          "too complex. ignoring.");
+                       return 0;
+               } else if (api->match_icmp_type_num > 1 &&
+                          enumerate_icmp == false) {
+                       if (BGP_DEBUG(pbr, PBR))
+                               zlog_debug("BGP: match icmp code is enumerate"
+                                          ", and icmp type is not."
+                                          " too complex. ignoring.");
+                       return 0;
+               }
+       }
        if (!bgp_pbr_extract(api->port, api->match_port_num, NULL)) {
                if (BGP_DEBUG(pbr, PBR))
                        zlog_debug("BGP: match port operations:"
                                 "too complex. ignoring.");
                return 0;
        }
+       if (api->match_packet_length_num) {
+               bool ret;
+
+               ret = bgp_pbr_extract(api->packet_length,
+                                     api->match_packet_length_num, NULL);
+               if (!ret)
+                       ret = bgp_pbr_extract_enumerate(api->packet_length,
+                                               api->match_packet_length_num,
+                                               OPERATOR_UNARY_OR
+                                               | OPERATOR_UNARY_AND,
+                                               NULL, FLOWSPEC_PKT_LEN);
+               if (!ret) {
+                       if (BGP_DEBUG(pbr, PBR))
+                               zlog_debug("BGP: match packet length operations:"
+                                  "too complex. ignoring.");
+                       return 0;
+               }
+       }
+       if (api->match_dscp_num) {
+               if (!bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
+                               OPERATOR_UNARY_OR | OPERATOR_UNARY_AND,
+                                              NULL, FLOWSPEC_DSCP)) {
+                       if (BGP_DEBUG(pbr, PBR))
+                               zlog_debug("BGP: match DSCP operations:"
+                                          "too complex. ignoring.");
+                       return 0;
+               }
+       }
+       if (api->match_fragment_num) {
+               char fail_str[64];
+               bool success;
+
+               success = bgp_pbr_extract_enumerate(api->fragment,
+                                                   api->match_fragment_num,
+                                                   OPERATOR_UNARY_OR
+                                                   | OPERATOR_UNARY_AND,
+                                                   NULL, FLOWSPEC_FRAGMENT);
+               if (success) {
+                       int i;
+
+                       for (i = 0; i < api->match_fragment_num; i++) {
+                               if (api->fragment[i].value != 1 &&
+                                   api->fragment[i].value != 2 &&
+                                   api->fragment[i].value != 4 &&
+                                   api->fragment[i].value != 8) {
+                                       success = false;
+                                       sprintf(fail_str,
+                                               "Value not valid (%d) for this implementation",
+                                               api->fragment[i].value);
+                               }
+                       }
+               } else
+                       sprintf(fail_str, "too complex. ignoring");
+               if (!success) {
+                       if (BGP_DEBUG(pbr, PBR))
+                               zlog_debug("BGP: match fragment operation (%d) %s",
+                                          api->match_fragment_num,
+                                          fail_str);
+                       return 0;
+               }
+       }
+
        /* no combinations with both src_port and dst_port
         * or port with src_port and dst_port
         */
@@ -294,6 +601,14 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
                                 " too complex. ignoring.");
                return 0;
        }
+       if ((api->match_src_port_num || api->match_dst_port_num
+            || api->match_port_num) && (api->match_icmp_type_num
+                                        || api->match_icmp_code_num)) {
+               if (BGP_DEBUG(pbr, PBR))
+                       zlog_debug("BGP: match multiple port/imcp operations:"
+                                " too complex. ignoring.");
+               return 0;
+       }
        if (!(api->match_bitmask & PREFIX_SRC_PRESENT) &&
            !(api->match_bitmask & PREFIX_DST_PRESENT)) {
                if (BGP_DEBUG(pbr, PBR)) {
@@ -518,6 +833,12 @@ uint32_t bgp_pbr_match_hash_key(void *arg)
 
        key = jhash_1word(pbm->vrf_id, 0x4312abde);
        key = jhash_1word(pbm->flags, key);
+       key = jhash_1word(pbm->pkt_len_min, key);
+       key = jhash_1word(pbm->pkt_len_max, key);
+       key = jhash_1word(pbm->tcp_flags, key);
+       key = jhash_1word(pbm->tcp_mask_flags, key);
+       key = jhash_1word(pbm->dscp_value, key);
+       key = jhash_1word(pbm->fragment, key);
        return jhash_1word(pbm->type, key);
 }
 
@@ -540,6 +861,23 @@ int bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
        if (r1->action != r2->action)
                return 0;
 
+       if (r1->pkt_len_min != r2->pkt_len_min)
+               return 0;
+
+       if (r1->pkt_len_max != r2->pkt_len_max)
+               return 0;
+
+       if (r1->tcp_flags != r2->tcp_flags)
+               return 0;
+
+       if (r1->tcp_mask_flags != r2->tcp_mask_flags)
+               return 0;
+
+       if (r1->dscp_value != r2->dscp_value)
+               return 0;
+
+       if (r1->fragment != r2->fragment)
+               return 0;
        return 1;
 }
 
@@ -807,10 +1145,11 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
                ptr += sprintf_bgp_pbr_match_val(ptr, &api->tcpflags[i],
                                         i > 0 ? NULL : "@tcpflags ");
 
-       if (api->match_bitmask & FRAGMENT_PRESENT) {
+       if (api->match_fragment_num)
                INCREMENT_DISPLAY(ptr, nb_items);
-               ptr += sprintf(ptr, "@fragment %u", api->fragment.bitmask);
-       }
+       for (i = 0; i < api->match_fragment_num; i++)
+               ptr += sprintf_bgp_pbr_match_val(ptr, &api->fragment[i],
+                                        i > 0 ? NULL : "@fragment ");
        if (!nb_items)
                ptr = return_string;
        else
@@ -953,20 +1292,24 @@ static int bgp_pbr_get_remaining_entry(struct hash_backet *backet, void *arg)
        return HASHWALK_ABORT;
 }
 
-static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
-                                         struct bgp_info *binfo,
-                                         vrf_id_t vrf_id,
-                                         struct prefix *src,
-                                         struct prefix *dst,
-                                         uint8_t protocol,
-                                         struct bgp_pbr_range_port *src_port,
-                                         struct bgp_pbr_range_port *dst_port)
+static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp,
+                               struct bgp_info *binfo,
+                               struct bgp_pbr_filter *bpf)
 {
        struct bgp_pbr_match temp;
        struct bgp_pbr_match_entry temp2;
        struct bgp_pbr_match *bpm;
        struct bgp_pbr_match_entry *bpme;
        struct bgp_pbr_match_entry_remain bpmer;
+       struct bgp_pbr_range_port *src_port;
+       struct bgp_pbr_range_port *dst_port;
+       struct bgp_pbr_range_port *pkt_len;
+
+       if (!bpf)
+               return;
+       src_port = bpf->src_port;
+       dst_port = bpf->dst_port;
+       pkt_len = bpf->pkt_len;
 
        /* as we don't know information from EC
         * look for bpm that have the bpm
@@ -974,17 +1317,19 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
         */
        memset(&temp2, 0, sizeof(temp2));
        memset(&temp, 0, sizeof(temp));
-       if (src) {
+       if (bpf->src) {
                temp.flags |= MATCH_IP_SRC_SET;
-               prefix_copy(&temp2.src, src);
+               prefix_copy(&temp2.src, bpf->src);
        } else
                temp2.src.family = AF_INET;
-       if (dst) {
+       if (bpf->dst) {
                temp.flags |= MATCH_IP_DST_SET;
-               prefix_copy(&temp2.dst, dst);
+               prefix_copy(&temp2.dst, bpf->dst);
        } else
                temp2.dst.family = AF_INET;
-       if (src_port) {
+       if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
+               if (bpf->protocol == IPPROTO_ICMP)
+                       temp.flags |= MATCH_ICMP_SET;
                temp.flags |= MATCH_PORT_SRC_SET;
                temp2.src_port_min = src_port->min_port;
                if (src_port->max_port) {
@@ -992,7 +1337,9 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
                        temp2.src_port_max = src_port->max_port;
                }
        }
-       if (dst_port) {
+       if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
+               if (bpf->protocol == IPPROTO_ICMP)
+                       temp.flags |= MATCH_ICMP_SET;
                temp.flags |= MATCH_PORT_DST_SET;
                temp2.dst_port_min = dst_port->min_port;
                if (dst_port->max_port) {
@@ -1000,9 +1347,35 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
                        temp2.dst_port_max = dst_port->max_port;
                }
        }
-       temp2.proto = protocol;
+       temp2.proto = bpf->protocol;
+
+       if (pkt_len) {
+               temp.pkt_len_min = pkt_len->min_port;
+               if (pkt_len->max_port)
+                       temp.pkt_len_max = pkt_len->max_port;
+       } else if (bpf->pkt_len_val) {
+               if (bpf->pkt_len_val->mask)
+                       temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
+               temp.pkt_len_min = bpf->pkt_len_val->val;
+       }
+       if (bpf->tcp_flags) {
+               temp.tcp_flags = bpf->tcp_flags->val;
+               temp.tcp_mask_flags = bpf->tcp_flags->mask;
+       }
+       if (bpf->dscp) {
+               if (bpf->dscp->mask)
+                       temp.flags |= MATCH_DSCP_INVERSE_SET;
+               else
+                       temp.flags |= MATCH_DSCP_SET;
+               temp.dscp_value = bpf->dscp->val;
+       }
+       if (bpf->fragment) {
+               if (bpf->fragment->mask)
+                       temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
+               temp.fragment = bpf->fragment->val;
+       }
 
-       if (src == NULL || dst == NULL) {
+       if (bpf->src == NULL || bpf->dst == NULL) {
                if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
                        temp.type = IPSET_NET_PORT;
                else
@@ -1013,10 +1386,10 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
                else
                        temp.type = IPSET_NET_NET;
        }
-       if (vrf_id == VRF_UNKNOWN) /* XXX case BGP destroy */
+       if (bpf->vrf_id == VRF_UNKNOWN) /* XXX case BGP destroy */
                temp.vrf_id = 0;
        else
-               temp.vrf_id = vrf_id;
+               temp.vrf_id = bpf->vrf_id;
        bpme = &temp2;
        bpm = &temp;
        bpme->backpointer = bpm;
@@ -1037,16 +1410,182 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
        }
 }
 
-static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
+static uint8_t bgp_pbr_next_type_entry(uint8_t type_entry)
+{
+       if (type_entry == FLOWSPEC_TCP_FLAGS)
+               return FLOWSPEC_DSCP;
+       if (type_entry == FLOWSPEC_DSCP)
+               return FLOWSPEC_PKT_LEN;
+       if (type_entry == FLOWSPEC_PKT_LEN)
+               return FLOWSPEC_FRAGMENT;
+       if (type_entry == FLOWSPEC_FRAGMENT)
+               return FLOWSPEC_ICMP_TYPE;
+       return 0;
+}
+
+static void  bgp_pbr_icmp_action(struct bgp *bgp,
+                                struct bgp_info *binfo,
+                                struct bgp_pbr_filter *bpf,
+                                struct bgp_pbr_or_filter *bpof,
+                                bool add,
+                                struct nexthop *nh,
+                                float *rate)
+{
+       struct bgp_pbr_range_port srcp, dstp;
+       struct bgp_pbr_val_mask *icmp_type, *icmp_code;
+       struct listnode *tnode, *cnode;
+
+       if (!bpf)
+               return;
+       if (bpf->protocol != IPPROTO_ICMP)
+               return;
+       bpf->src_port = &srcp;
+       bpf->dst_port = &dstp;
+       /* parse icmp type and lookup appropriate icmp code
+        * if no icmp code found, create as many entryes as
+        * there are listed icmp codes for that icmp type
+        */
+       if (!bpof->icmp_type) {
+               srcp.min_port = 0;
+               srcp.max_port = 255;
+               for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
+                       dstp.min_port = icmp_code->val;
+                       if (add)
+                               bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo,
+                                                       bpf, nh, rate);
+                       else
+                               bgp_pbr_policyroute_remove_from_zebra_unit(
+                                                       bgp, binfo, bpf);
+               }
+               return;
+       }
+       for (ALL_LIST_ELEMENTS_RO(bpof->icmp_type, tnode, icmp_type)) {
+               srcp.min_port = icmp_type->val;
+               srcp.max_port = 0;
+               dstp.max_port = 0;
+               /* only icmp type. create an entry only with icmp type */
+               if (!bpof->icmp_code) {
+                       /* icmp type is not one of the above
+                        * forge an entry only based on the icmp type
+                        */
+                       dstp.min_port = 0;
+                       dstp.max_port = 255;
+                       if (add)
+                               bgp_pbr_policyroute_add_to_zebra_unit(
+                                                       bgp, binfo,
+                                                       bpf, nh, rate);
+                       else
+                               bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
+                                                             binfo, bpf);
+                       continue;
+               }
+               for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
+                       dstp.min_port = icmp_code->val;
+                       if (add)
+                               bgp_pbr_policyroute_add_to_zebra_unit(
+                                                       bgp, binfo,
+                                                       bpf, nh, rate);
+                       else
+                               bgp_pbr_policyroute_remove_from_zebra_unit(
+                                                          bgp, binfo, bpf);
+               }
+       }
+}
+
+static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp,
+                       struct bgp_info *binfo,
+                       struct bgp_pbr_filter *bpf,
+                       struct bgp_pbr_or_filter *bpof,
+                       uint8_t type_entry)
+{
+       struct listnode *node, *nnode;
+       struct bgp_pbr_val_mask *valmask;
+       uint8_t next_type_entry;
+       struct list *orig_list;
+       struct bgp_pbr_val_mask **target_val;
+
+       if (type_entry == 0)
+               return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
+                                                       binfo, bpf);
+       next_type_entry = bgp_pbr_next_type_entry(type_entry);
+       if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
+               orig_list = bpof->tcpflags;
+               target_val = &bpf->tcp_flags;
+       } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
+               orig_list = bpof->dscp;
+               target_val = &bpf->dscp;
+       } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
+               orig_list = bpof->pkt_len;
+               target_val = &bpf->pkt_len_val;
+       } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
+               orig_list = bpof->fragment;
+               target_val = &bpf->fragment;
+       } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
+                  (bpof->icmp_type || bpof->icmp_code)) {
+               /* enumerate list for icmp - must be last one  */
+               bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, false, NULL, NULL);
+               return;
+       } else {
+               return bgp_pbr_policyroute_remove_from_zebra_recursive(bgp,
+                                                       binfo,
+                                                       bpf, bpof,
+                                                       next_type_entry);
+       }
+       for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
+               *target_val = valmask;
+               bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+                                                       bpf, bpof,
+                                                       next_type_entry);
+       }
+}
+
+static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
+                               struct bgp_info *binfo,
+                               struct bgp_pbr_filter *bpf,
+                               struct bgp_pbr_or_filter *bpof)
+{
+       if (!bpof)
+               return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
+                                                                 binfo,
+                                                                 bpf);
+       if (bpof->tcpflags)
+               bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+                                                       bpf, bpof,
+                                                       FLOWSPEC_TCP_FLAGS);
+       else if (bpof->dscp)
+               bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+                                                       bpf, bpof,
+                                                       FLOWSPEC_DSCP);
+       else if (bpof->pkt_len)
+               bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+                                                       bpf, bpof,
+                                                       FLOWSPEC_PKT_LEN);
+       else if (bpof->fragment)
+               bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+                                                       bpf, bpof,
+                                                       FLOWSPEC_FRAGMENT);
+       else if (bpof->icmp_type || bpof->icmp_code)
+               bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
+                                                       bpf, bpof,
+                                                       FLOWSPEC_ICMP_TYPE);
+       else
+               bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf);
+       /* flush bpof */
+       if (bpof->tcpflags)
+               list_delete_all_node(bpof->tcpflags);
+       if (bpof->dscp)
+               list_delete_all_node(bpof->dscp);
+       if (bpof->pkt_len)
+               list_delete_all_node(bpof->pkt_len);
+       if (bpof->fragment)
+               list_delete_all_node(bpof->fragment);
+}
+
+static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
                                     struct bgp_info *binfo,
-                                    vrf_id_t vrf_id,
-                                    struct prefix *src,
-                                    struct prefix *dst,
+                                    struct bgp_pbr_filter *bpf,
                                     struct nexthop *nh,
-                                    float *rate,
-                                    uint8_t protocol,
-                                    struct bgp_pbr_range_port *src_port,
-                                    struct bgp_pbr_range_port *dst_port)
+                                    float *rate)
 {
        struct bgp_pbr_match temp;
        struct bgp_pbr_match_entry temp2;
@@ -1055,14 +1594,104 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
        struct bgp_pbr_action temp3;
        struct bgp_pbr_action *bpa = NULL;
        struct bgp_pbr_match_entry_remain bpmer;
+       struct bgp_pbr_range_port *src_port;
+       struct bgp_pbr_range_port *dst_port;
+       struct bgp_pbr_range_port *pkt_len;
 
+       if (!bpf)
+               return;
+       src_port = bpf->src_port;
+       dst_port = bpf->dst_port;
+       pkt_len = bpf->pkt_len;
+
+       if (BGP_DEBUG(zebra, ZEBRA)) {
+               char bufsrc[64], bufdst[64];
+               char buffer[64];
+               int remaining_len = 0;
+               char protocol_str[16];
+
+               protocol_str[0] = '\0';
+               if (bpf->tcp_flags && bpf->tcp_flags->mask)
+                       bpf->protocol = IPPROTO_TCP;
+               if (bpf->protocol)
+                       snprintf(protocol_str, sizeof(protocol_str),
+                                "proto %d", bpf->protocol);
+               buffer[0] = '\0';
+               if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port)
+                       remaining_len += snprintf(buffer, sizeof(buffer),
+                                                 "type %d, code %d",
+                                src_port->min_port, dst_port->min_port);
+               else if (bpf->protocol == IPPROTO_UDP ||
+                        bpf->protocol == IPPROTO_TCP) {
+
+                       if (src_port && src_port->min_port)
+                               remaining_len += snprintf(buffer,
+                                                         sizeof(buffer),
+                                                         "from [%u:%u]",
+                                                         src_port->min_port,
+                                                         src_port->max_port ?
+                                                         src_port->max_port :
+                                                         src_port->min_port);
+                       if (dst_port && dst_port->min_port)
+                               remaining_len += snprintf(buffer +
+                                                         remaining_len,
+                                                         sizeof(buffer)
+                                                         - remaining_len,
+                                                         "to [%u:%u]",
+                                                         dst_port->min_port,
+                                                         dst_port->max_port ?
+                                                         dst_port->max_port :
+                                                         dst_port->min_port);
+               }
+               if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) {
+                       remaining_len += snprintf(buffer + remaining_len,
+                                                 sizeof(buffer)
+                                                 - remaining_len,
+                                                 " len [%u:%u]",
+                                                 pkt_len->min_port,
+                                                 pkt_len->max_port ?
+                                                 pkt_len->max_port :
+                                                 pkt_len->min_port);
+               } else if (bpf->pkt_len_val) {
+                       remaining_len += snprintf(buffer + remaining_len,
+                                                 sizeof(buffer)
+                                                 - remaining_len,
+                                                 " %s len %u",
+                                                 bpf->pkt_len_val->mask
+                                                 ? "!" : "",
+                                                 bpf->pkt_len_val->val);
+               }
+               if (bpf->tcp_flags) {
+                       remaining_len += snprintf(buffer + remaining_len,
+                                                 sizeof(buffer)
+                                                 - remaining_len,
+                                                 "tcpflags %x/%x",
+                                                 bpf->tcp_flags->val,
+                                                 bpf->tcp_flags->mask);
+               }
+               if (bpf->dscp) {
+                       snprintf(buffer + remaining_len,
+                                sizeof(buffer)
+                                - remaining_len,
+                                "%s dscp %d",
+                                bpf->dscp->mask
+                                ? "!" : "",
+                                bpf->dscp->val);
+               }
+               zlog_info("BGP: adding FS PBR from %s to %s, %s %s",
+                         bpf->src == NULL ? "<all>" :
+                         prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
+                         bpf->dst == NULL ? "<all>" :
+                         prefix2str(bpf->dst, bufdst, sizeof(bufdst)),
+                         protocol_str, buffer);
+       }
        /* look for bpa first */
        memset(&temp3, 0, sizeof(temp3));
        if (rate)
                temp3.rate = *rate;
        if (nh)
                memcpy(&temp3.nh, nh, sizeof(struct nexthop));
-       temp3.vrf_id = vrf_id;
+       temp3.vrf_id = bpf->vrf_id;
        bpa = hash_get(bgp->pbr_action_hash, &temp3,
                       bgp_pbr_action_alloc_intern);
 
@@ -1084,33 +1713,63 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
 
        /* then look for bpm */
        memset(&temp, 0, sizeof(temp));
-       if (src == NULL || dst == NULL) {
-               if ((src_port && src_port->min_port) ||
-                   (dst_port && dst_port->min_port))
-                       temp.type = IPSET_NET_PORT;
-               else
-                       temp.type = IPSET_NET;
-       } else {
-               if ((src_port && src_port->min_port) ||
-                   (dst_port && dst_port->min_port))
-                       temp.type = IPSET_NET_PORT_NET;
-               else
-                       temp.type = IPSET_NET_NET;
-       }
-       temp.vrf_id = vrf_id;
-       if (src)
+       temp.vrf_id = bpf->vrf_id;
+       if (bpf->src)
                temp.flags |= MATCH_IP_SRC_SET;
-       if (dst)
+       if (bpf->dst)
                temp.flags |= MATCH_IP_DST_SET;
 
-       if (src_port && src_port->min_port)
+       if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
+               if (bpf->protocol == IPPROTO_ICMP)
+                       temp.flags |= MATCH_ICMP_SET;
                temp.flags |= MATCH_PORT_SRC_SET;
-       if (dst_port && dst_port->min_port)
+       }
+       if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
+               if (bpf->protocol == IPPROTO_ICMP)
+                       temp.flags |= MATCH_ICMP_SET;
                temp.flags |= MATCH_PORT_DST_SET;
+       }
        if (src_port && src_port->max_port)
                temp.flags |= MATCH_PORT_SRC_RANGE_SET;
        if (dst_port && dst_port->max_port)
                temp.flags |= MATCH_PORT_DST_RANGE_SET;
+
+       if (bpf->src == NULL || bpf->dst == NULL) {
+               if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
+                       temp.type = IPSET_NET_PORT;
+               else
+                       temp.type = IPSET_NET;
+       } else {
+               if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
+                       temp.type = IPSET_NET_PORT_NET;
+               else
+                       temp.type = IPSET_NET_NET;
+       }
+       if (pkt_len) {
+               temp.pkt_len_min = pkt_len->min_port;
+               if (pkt_len->max_port)
+                       temp.pkt_len_max = pkt_len->max_port;
+       } else if (bpf->pkt_len_val) {
+               if (bpf->pkt_len_val->mask)
+                       temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
+               temp.pkt_len_min = bpf->pkt_len_val->val;
+       }
+       if (bpf->tcp_flags) {
+               temp.tcp_flags = bpf->tcp_flags->val;
+               temp.tcp_mask_flags = bpf->tcp_flags->mask;
+       }
+       if (bpf->dscp) {
+               if (bpf->dscp->mask)
+                       temp.flags |= MATCH_DSCP_INVERSE_SET;
+               else
+                       temp.flags |= MATCH_DSCP_SET;
+               temp.dscp_value = bpf->dscp->val;
+       }
+       if (bpf->fragment) {
+               if (bpf->fragment->mask)
+                       temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
+               temp.fragment = bpf->fragment->val;
+       }
        temp.action = bpa;
        bpm = hash_get(bgp->pbr_match_hash, &temp,
                       bgp_pbr_match_alloc_intern);
@@ -1134,19 +1793,19 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
        }
 
        memset(&temp2, 0, sizeof(temp2));
-       if (src)
-               prefix_copy(&temp2.src, src);
+       if (bpf->src)
+               prefix_copy(&temp2.src, bpf->src);
        else
                temp2.src.family = AF_INET;
-       if (dst)
-               prefix_copy(&temp2.dst, dst);
+       if (bpf->dst)
+               prefix_copy(&temp2.dst, bpf->dst);
        else
                temp2.dst.family = AF_INET;
        temp2.src_port_min = src_port ? src_port->min_port : 0;
        temp2.dst_port_min = dst_port ? dst_port->min_port : 0;
        temp2.src_port_max = src_port ? src_port->max_port : 0;
        temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
-       temp2.proto = protocol;
+       temp2.proto = bpf->protocol;
        if (bpm)
                bpme = hash_get(bpm->entry_hash, &temp2,
                                bgp_pbr_match_entry_alloc_intern);
@@ -1171,7 +1830,7 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
         * it will be suppressed subsequently
         */
        /* ip rule add */
-       if (!bpa->installed) {
+       if (!bpa->installed && !bpa->install_in_progress) {
                bgp_send_pbr_rule_action(bpa, true);
                bgp_zebra_announce_default(bgp, nh,
                                           AFI_IP, bpa->table_id, true);
@@ -1207,6 +1866,107 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
 
 }
 
+static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp,
+                       struct bgp_info *binfo,
+                       struct bgp_pbr_filter *bpf,
+                       struct bgp_pbr_or_filter *bpof,
+                       struct nexthop *nh,
+                       float *rate,
+                       uint8_t type_entry)
+{
+       struct listnode *node, *nnode;
+       struct bgp_pbr_val_mask *valmask;
+       uint8_t next_type_entry;
+       struct list *orig_list;
+       struct bgp_pbr_val_mask **target_val;
+
+       if (type_entry == 0)
+               return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
+                                                            nh, rate);
+       next_type_entry = bgp_pbr_next_type_entry(type_entry);
+       if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
+               orig_list = bpof->tcpflags;
+               target_val = &bpf->tcp_flags;
+       } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
+               orig_list = bpof->dscp;
+               target_val = &bpf->dscp;
+       } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
+               orig_list = bpof->pkt_len;
+               target_val = &bpf->pkt_len_val;
+       } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
+               orig_list = bpof->fragment;
+               target_val = &bpf->fragment;
+       } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
+                  (bpof->icmp_type || bpof->icmp_code)) {
+               /* enumerate list for icmp - must be last one  */
+               bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, true, nh, rate);
+               return;
+       } else {
+               return bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+                                               bpf, bpof, nh, rate,
+                                               next_type_entry);
+       }
+       for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
+               *target_val = valmask;
+               bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+                                                       bpf, bpof,
+                                                       nh, rate,
+                                                       next_type_entry);
+       }
+}
+
+static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
+                                    struct bgp_info *binfo,
+                                    struct bgp_pbr_filter *bpf,
+                                    struct bgp_pbr_or_filter *bpof,
+                                    struct nexthop *nh,
+                                    float *rate)
+{
+       if (!bpof)
+               return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo,
+                                                            bpf, nh, rate);
+       if (bpof->tcpflags)
+               bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+                                                          bpf, bpof,
+                                                          nh, rate,
+                                                          FLOWSPEC_TCP_FLAGS);
+       else if (bpof->dscp)
+               bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+                                                          bpf, bpof,
+                                                          nh, rate,
+                                                          FLOWSPEC_DSCP);
+       else if (bpof->pkt_len)
+               bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+                                                          bpf, bpof,
+                                                          nh, rate,
+                                                          FLOWSPEC_PKT_LEN);
+       else if (bpof->fragment)
+               bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+                                                          bpf, bpof,
+                                                          nh, rate,
+                                                          FLOWSPEC_FRAGMENT);
+       else if (bpof->icmp_type || bpof->icmp_code)
+               bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
+                                                  bpf, bpof, nh, rate,
+                                                  FLOWSPEC_ICMP_TYPE);
+       else
+               bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
+                                                     nh, rate);
+       /* flush bpof */
+       if (bpof->tcpflags)
+               list_delete_all_node(bpof->tcpflags);
+       if (bpof->dscp)
+               list_delete_all_node(bpof->dscp);
+       if (bpof->pkt_len)
+               list_delete_all_node(bpof->pkt_len);
+       if (bpof->fragment)
+               list_delete_all_node(bpof->fragment);
+       if (bpof->icmp_type)
+               list_delete_all_node(bpof->icmp_type);
+       if (bpof->icmp_code)
+               list_delete_all_node(bpof->icmp_code);
+}
+
 static void bgp_pbr_handle_entry(struct bgp *bgp,
                                struct bgp_info *binfo,
                                struct bgp_pbr_entry_main *api,
@@ -1219,9 +1979,16 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
        struct prefix *src = NULL, *dst = NULL;
        uint8_t proto = 0;
        struct bgp_pbr_range_port *srcp = NULL, *dstp = NULL;
-       struct bgp_pbr_range_port range;
+       struct bgp_pbr_range_port range, range_icmp_code;
+       struct bgp_pbr_range_port pkt_len;
+       struct bgp_pbr_filter bpf;
+       uint8_t kind_enum;
+       struct bgp_pbr_or_filter bpof;
+       struct bgp_pbr_val_mask bpvm;
 
        memset(&nh, 0, sizeof(struct nexthop));
+       memset(&bpf, 0, sizeof(struct bgp_pbr_filter));
+       memset(&bpof, 0, sizeof(struct bgp_pbr_or_filter));
        if (api->match_bitmask & PREFIX_SRC_PRESENT)
                src = &api->src_prefix;
        if (api->match_bitmask & PREFIX_DST_PRESENT)
@@ -1251,10 +2018,97 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
                dstp = &range;
                srcp = NULL;
        }
+       if (api->match_icmp_type_num >= 1) {
+               proto = IPPROTO_ICMP;
+               if (bgp_pbr_extract(api->icmp_type,
+                                   api->match_icmp_type_num,
+                                   &range))
+                       srcp = &range;
+               else {
+                       bpof.icmp_type = list_new();
+                       bgp_pbr_extract_enumerate(api->icmp_type,
+                                                 api->match_icmp_type_num,
+                                                 OPERATOR_UNARY_OR,
+                                                 bpof.icmp_type,
+                                                 FLOWSPEC_ICMP_TYPE);
+               }
+       }
+       if (api->match_icmp_code_num >= 1) {
+               proto = IPPROTO_ICMP;
+               if (bgp_pbr_extract(api->icmp_code,
+                                   api->match_icmp_code_num,
+                                   &range_icmp_code))
+                       dstp = &range_icmp_code;
+               else {
+                       bpof.icmp_code = list_new();
+                       bgp_pbr_extract_enumerate(api->icmp_code,
+                                                 api->match_icmp_code_num,
+                                                 OPERATOR_UNARY_OR,
+                                                 bpof.icmp_code,
+                                                 FLOWSPEC_ICMP_CODE);
+               }
+       }
+
+       if (api->match_tcpflags_num) {
+               kind_enum = bgp_pbr_match_val_get_operator(api->tcpflags,
+                                                  api->match_tcpflags_num);
+               if (kind_enum == OPERATOR_UNARY_AND) {
+                       bpf.tcp_flags = &bpvm;
+                       bgp_pbr_extract_enumerate(api->tcpflags,
+                                                 api->match_tcpflags_num,
+                                                 OPERATOR_UNARY_AND,
+                                                 bpf.tcp_flags,
+                                                 FLOWSPEC_TCP_FLAGS);
+               } else if (kind_enum == OPERATOR_UNARY_OR) {
+                       bpof.tcpflags = list_new();
+                       bgp_pbr_extract_enumerate(api->tcpflags,
+                                                 api->match_tcpflags_num,
+                                                 OPERATOR_UNARY_OR,
+                                                 bpof.tcpflags,
+                                                 FLOWSPEC_TCP_FLAGS);
+               }
+       }
+       if (api->match_packet_length_num) {
+               bool ret;
+
+               ret = bgp_pbr_extract(api->packet_length,
+                                     api->match_packet_length_num,
+                                     &pkt_len);
+               if (ret)
+                       bpf.pkt_len = &pkt_len;
+               else {
+                       bpof.pkt_len = list_new();
+                       bgp_pbr_extract_enumerate(api->packet_length,
+                                                 api->match_packet_length_num,
+                                                 OPERATOR_UNARY_OR,
+                                                 bpof.pkt_len,
+                                                 FLOWSPEC_PKT_LEN);
+               }
+       }
+       if (api->match_dscp_num >= 1) {
+               bpof.dscp = list_new();
+               bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
+                                         OPERATOR_UNARY_OR,
+                                         bpof.dscp, FLOWSPEC_DSCP);
+       }
+       if (api->match_fragment_num) {
+               bpof.fragment = list_new();
+               bgp_pbr_extract_enumerate(api->fragment,
+                                         api->match_fragment_num,
+                                         OPERATOR_UNARY_OR,
+                                         bpof.fragment,
+                                         FLOWSPEC_FRAGMENT);
+       }
+       bpf.vrf_id = api->vrf_id;
+       bpf.src = src;
+       bpf.dst = dst;
+       bpf.protocol = proto;
+       bpf.src_port = srcp;
+       bpf.dst_port = dstp;
        if (!add)
-               return bgp_pbr_policyroute_remove_from_zebra(bgp, binfo,
-                                            api->vrf_id, src, dst,
-                                            proto, srcp, dstp);
+               return bgp_pbr_policyroute_remove_from_zebra(bgp,
+                                                            binfo,
+                                                            &bpf, &bpof);
        /* no action for add = true */
        for (i = 0; i < api->action_num; i++) {
                switch (api->actions[i].action) {
@@ -1264,9 +2118,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
                                nh.vrf_id = api->vrf_id;
                                nh.type = NEXTHOP_TYPE_BLACKHOLE;
                                bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
-                                                   api->vrf_id, src, dst,
-                                                   &nh, &rate, proto,
-                                                   srcp, dstp);
+                                                                &bpf, &bpof,
+                                                                &nh, &rate);
                        } else {
                                /* update rate. can be reentrant */
                                rate = api->actions[i].u.r.rate;
@@ -1307,10 +2160,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
                                api->actions[i].u.zr.redirect_ip_v4.s_addr;
                        nh.vrf_id = api->vrf_id;
                        bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
-                                                           api->vrf_id,
-                                                           src, dst,
-                                                           &nh, &rate, proto,
-                                                           srcp, dstp);
+                                                        &bpf, &bpof,
+                                                        &nh, &rate);
                        /* XXX combination with REDIRECT_VRF
                         * + REDIRECT_NH_IP not done
                         */
@@ -1320,10 +2171,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
                        nh.vrf_id = api->actions[i].u.redirect_vrf;
                        nh.type = NEXTHOP_TYPE_IPV4;
                        bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
-                                                        api->vrf_id,
-                                                        src, dst,
-                                                        &nh, &rate, proto,
-                                                        srcp, dstp);
+                                                        &bpf, &bpof,
+                                                        &nh, &rate);
                        continue_loop = 0;
                        break;
                case ACTION_MARKING:
index 20edaf30b8a567fa5bf70a6f73e73375ef6cb276..307a34e34f4c02749f49604601b0cc90b9151532 100644 (file)
@@ -107,7 +107,6 @@ struct bgp_pbr_entry_main {
 
 #define PREFIX_SRC_PRESENT (1 << 0)
 #define PREFIX_DST_PRESENT (1 << 1)
-#define FRAGMENT_PRESENT   (1 << 2)
        uint8_t match_bitmask;
 
        uint8_t match_src_port_num;
@@ -119,12 +118,14 @@ struct bgp_pbr_entry_main {
        uint8_t match_packet_length_num;
        uint8_t match_dscp_num;
        uint8_t match_tcpflags_num;
+       uint8_t match_fragment_num;
 
        struct prefix src_prefix;
        struct prefix dst_prefix;
 
 #define PROTOCOL_UDP 17
 #define PROTOCOL_TCP 6
+#define PROTOCOL_ICMP 1
        struct bgp_pbr_match_val protocol[BGP_PBR_MATCH_VAL_MAX];
        struct bgp_pbr_match_val src_port[BGP_PBR_MATCH_VAL_MAX];
        struct bgp_pbr_match_val dst_port[BGP_PBR_MATCH_VAL_MAX];
@@ -133,8 +134,9 @@ struct bgp_pbr_entry_main {
        struct bgp_pbr_match_val icmp_code[BGP_PBR_MATCH_VAL_MAX];
        struct bgp_pbr_match_val packet_length[BGP_PBR_MATCH_VAL_MAX];
        struct bgp_pbr_match_val dscp[BGP_PBR_MATCH_VAL_MAX];
+
        struct bgp_pbr_match_val tcpflags[BGP_PBR_MATCH_VAL_MAX];
-       struct bgp_pbr_fragment_val fragment;
+       struct bgp_pbr_match_val fragment[BGP_PBR_MATCH_VAL_MAX];
 
        uint16_t action_num;
        struct bgp_pbr_entry_action actions[ACTIONS_MAX_NUM];
@@ -176,14 +178,15 @@ struct bgp_pbr_match {
         */
        uint32_t type;
 
-#define MATCH_IP_SRC_SET               (1 << 0)
-#define MATCH_IP_DST_SET               (1 << 1)
-#define MATCH_PORT_SRC_SET             (1 << 2)
-#define MATCH_PORT_DST_SET             (1 << 3)
-#define MATCH_PORT_SRC_RANGE_SET       (1 << 4)
-#define MATCH_PORT_DST_RANGE_SET       (1 << 5)
        uint32_t flags;
 
+       uint16_t pkt_len_min;
+       uint16_t pkt_len_max;
+       uint16_t tcp_flags;
+       uint16_t tcp_mask_flags;
+       uint8_t dscp_value;
+       uint8_t fragment;
+
        vrf_id_t vrf_id;
 
        /* unique identifier for ipset create transaction
index 0b1deba5171fb57ac64d4a9df0f7035aad95792f..7057b62f2b00a47271b8eaa19d28602ae7599392 100644 (file)
@@ -6282,7 +6282,6 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty,
                prefix2str(p, buf, PREFIX_STRLEN);
                len = vty_out(vty, "%s", buf);
        } else if (p->family == AF_EVPN) {
-#if defined(HAVE_CUMULUS)
                if (!json)
                        len = vty_out(
                                vty, "%s",
@@ -6290,10 +6289,6 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty,
                                                   BUFSIZ));
                else
                        bgp_evpn_route2json((struct prefix_evpn *)p, json);
-#else
-               prefix2str(p, buf, PREFIX_STRLEN);
-               len = vty_out(vty, "%s", buf);
-#endif
        } else if (p->family == AF_FLOWSPEC) {
                route_vty_out_flowspec(vty, p, NULL,
                               json ?
@@ -7301,9 +7296,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
 {
        char buf[INET6_ADDRSTRLEN];
        char buf1[BUFSIZ];
-#if defined(HAVE_CUMULUS)
        char buf2[EVPN_ROUTE_STRLEN];
-#endif
        struct attr *attr;
        int sockunion_vty_out(struct vty *, union sockunion *);
        time_t tbuf;
@@ -7336,7 +7329,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                json_nexthop_global = json_object_new_object();
        }
 
-#if defined(HAVE_CUMULUS)
        if (!json_paths && safi == SAFI_EVPN) {
                char tag_buf[30];
 
@@ -7366,7 +7358,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                        }
                }
        }
-#endif
 
        attr = binfo->attr;
 
@@ -8019,14 +8010,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                if (binfo->extra && binfo->extra->damp_info)
                        bgp_damp_info_vty(vty, binfo, json_path);
 
-/* Remote Label */
-#if defined(HAVE_CUMULUS)
+               /* Remote Label */
                if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0])
-                   && safi != SAFI_EVPN)
-#else
-               if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0]))
-#endif
-               {
+                   && safi != SAFI_EVPN) {
                        mpls_label_t label =
                                label_pton(&binfo->extra->label[0]);
                        if (json_paths)
@@ -8597,9 +8583,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
        struct listnode *node, *nnode;
        char buf1[RD_ADDRSTRLEN];
        char buf2[INET6_ADDRSTRLEN];
-#if defined(HAVE_CUMULUS)
        char buf3[EVPN_ROUTE_STRLEN];
-#endif
        char prefix_str[BUFSIZ];
        int count = 0;
        int best = 0;
@@ -8626,7 +8610,6 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                        json, "prefix",
                        prefix2str(p, prefix_str, sizeof(prefix_str)));
        } else {
-#if defined(HAVE_CUMULUS)
                if (safi == SAFI_EVPN)
                        vty_out(vty, "BGP routing table entry for %s%s%s\n",
                                prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
@@ -8644,29 +8627,10 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                                inet_ntop(p->family, &p->u.prefix, buf2,
                                          INET6_ADDRSTRLEN),
                                p->prefixlen);
-#else
-               if (p->family == AF_ETHERNET)
-                       prefix2str(p, buf2, INET6_ADDRSTRLEN);
-               else
-                       inet_ntop(p->family, &p->u.prefix, buf2,
-                                 INET6_ADDRSTRLEN);
-               vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
-                       ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
-                         || safi == SAFI_EVPN)
-                                ? prefix_rd2str(prd, buf1, sizeof(buf1))
-                                : ""),
-                       ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":"
-                                                                        : "",
-                       buf2, p->prefixlen);
-#endif
 
                if (has_valid_label)
                        vty_out(vty, "Local label: %d\n", label);
-#if defined(HAVE_CUMULUS)
                if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
-#else
-               if (bgp_labeled_safi(safi))
-#endif
                        vty_out(vty, "not allocated\n");
        }
 
index 2d808a6ffb2548e90be34b97b85e85242a34b60d..df3f9ddd6fd51c2b207b2b177ea79e01a9406406 100644 (file)
@@ -2219,6 +2219,12 @@ static void bgp_encode_pbr_iptable_match(struct stream *s,
        stream_putl(s, bpa->fwmark);
        stream_put(s, pbm->ipset_name,
                   ZEBRA_IPSET_NAME_SIZE);
+       stream_putw(s, pbm->pkt_len_min);
+       stream_putw(s, pbm->pkt_len_max);
+       stream_putw(s, pbm->tcp_flags);
+       stream_putw(s, pbm->tcp_mask_flags);
+       stream_putc(s, pbm->dscp_value);
+       stream_putc(s, pbm->fragment);
 }
 
 /* BGP has established connection with Zebra. */
index 64f36ec6e3d8e475ba975bdcad5caf944738c274..283949ab2a709bf60a3ad5449db3e82e17f73d2c 100644 (file)
@@ -1032,6 +1032,8 @@ static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer)
 
                else {
                        struct peer *peer1;
+
+                       assert(peer->group);
                        peer1 = listnode_head(peer->group->peer);
 
                        if (peer1)
@@ -2733,9 +2735,8 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
                if (peer->group) {
                        assert(group && peer->group == group);
                } else {
-                       struct listnode *pn;
-                       pn = listnode_lookup(bgp->peer, peer);
-                       list_delete_node(bgp->peer, pn);
+                       listnode_delete(bgp->peer, peer);
+
                        peer->group = group;
                        listnode_add_sort(bgp->peer, peer);
 
index 491741a35b0e5b74dc360bf58800b79bdb78986c..8553846c9025137bbf0b5a0db3f14b6cf60f522c 100644 (file)
@@ -4519,7 +4519,7 @@ void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty)
        if (VNC_EXPORT_ZEBRA_GRP_ENABLED(hc)) {
                redist++;
                vty_out(vty, "%sToZebra Groups={", (redist == 1 ? "" : " "));
-               if (hc->rfg_export_direct_bgp_l) {
+               if (hc->rfg_export_zebra_l) {
                        int cnt = 0;
                        struct listnode *node, *nnode;
                        struct rfapi_rfg_name *rfgn;
index 18a979e531ea26c6ba09072d68cc2ceede9b63e0..cd12edbccb1f9c47c30aadccd64f2684c9e93d27 100644 (file)
@@ -388,15 +388,11 @@ int rfapiStream2Vty(void *stream,                    /* input */
                return 1;
        }
 
-       if (stream) {
-               *vty = stream; /* VTYNL requires vty to be legit */
-               *fp = (int (*)(void *, const char *, ...))vty_out;
-               *outstream = stream;
-               *vty_newline = str_vty_newline(*vty);
-               return 1;
-       }
-
-       return 0;
+       *vty = stream; /* VTYNL requires vty to be legit */
+       *fp = (int (*)(void *, const char *, ...))vty_out;
+       *outstream = stream;
+       *vty_newline = str_vty_newline(*vty);
+       return 1;
 }
 
 /* called from bgpd/bgp_vty.c'route_vty_out() */
@@ -3021,9 +3017,9 @@ static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda,
                 * match un, vn addresses of NVEs
                 */
                if (pUn && (rfapi_ip_addr_cmp(pUn, &rfd->un_addr)))
-                       continue;
+                       break;
                if (pVn && (rfapi_ip_addr_cmp(pVn, &rfd->vn_addr)))
-                       continue;
+                       break;
 
 #if DEBUG_L2_EXTRA
                vnc_zlog_debug_verbose("%s: un, vn match", __func__);
index bba86d4c1ff07b4375860fe3943d6927835e6a97..c8ef829064b54bfa268ee21a284f49a8fec8f5c2 100644 (file)
@@ -622,7 +622,7 @@ static const char *lsp_bits2string(uint8_t lsp_bits, char *buf, size_t buf_size)
        pos += sprintf(pos, "%d/",
                       ISIS_MASK_LSP_PARTITION_BIT(lsp_bits) ? 1 : 0);
 
-       pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(lsp_bits) ? 1 : 0);
+       sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(lsp_bits) ? 1 : 0);
 
        return buf;
 }
@@ -1052,6 +1052,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
                                        uint8_t subtlv_len;
 
                                        if (IS_MPLS_TE(isisMplsTE)
+                                           && circuit->interface != NULL
                                            && HAS_LINK_PARAMS(
                                                       circuit->interface))
                                                /* Update Local and Remote IP
index 6e56870ebd8c432b1236f86f85bd222445a70e01..fd82b85f51e71e0d844b6d794029870a37b7a10e 100644 (file)
@@ -309,9 +309,9 @@ int isis_recv_pdu_p2p(struct isis_circuit *circuit, uint8_t *ssnpa)
        addr_len = sizeof(s_addr);
 
        /* we can read directly to the stream */
-       stream_recvfrom(circuit->rcv_stream, circuit->fd,
-                       circuit->interface->mtu, 0, (struct sockaddr *)&s_addr,
-                       (socklen_t *)&addr_len);
+       (void)stream_recvfrom(
+               circuit->rcv_stream, circuit->fd, circuit->interface->mtu, 0,
+               (struct sockaddr *)&s_addr, (socklen_t *)&addr_len);
 
        if (s_addr.sll_pkttype == PACKET_OUTGOING) {
                /*  Read the packet into discard buff */
index 2e2933db332b5925850a3b4d9cf1ade228b61c8b..556f2890cfbc22caee61a27ed0783f72bb3e799c 100644 (file)
@@ -1473,8 +1473,9 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue,
                vty_out(vty, "%-20s %-12s %-6u ",
                        vid2string(vertex, buff, sizeof(buff)),
                        vtype2string(vertex->type), vertex->d_N);
-               for (unsigned int i = 0; i < MAX(listcount(vertex->Adj_N),
-                                                listcount(vertex->parents));
+               for (unsigned int i = 0;
+                    i < MAX(vertex->Adj_N ? listcount(vertex->Adj_N) : 0,
+                            vertex->parents ? listcount(vertex->parents) : 0);
                     i++) {
                        if (anode) {
                                adj = listgetdata(anode);
index 2cfa3e748208158968754fa14ca314593b97d867..86649dd4952ec12dbdfec6c5272df9f8ce06ea8a 100644 (file)
@@ -186,26 +186,10 @@ void listnode_move_to_tail(struct list *l, struct listnode *n)
 
 void listnode_delete(struct list *list, void *val)
 {
-       struct listnode *node;
+       struct listnode *node = listnode_lookup(list, val);
 
-       assert(list);
-       for (node = list->head; node; node = node->next) {
-               if (node->data == val) {
-                       if (node->prev)
-                               node->prev->next = node->next;
-                       else
-                               list->head = node->next;
-
-                       if (node->next)
-                               node->next->prev = node->prev;
-                       else
-                               list->tail = node->prev;
-
-                       list->count--;
-                       listnode_free(node);
-                       return;
-               }
-       }
+       if (node)
+               list_delete_node(list, node);
 }
 
 void *listnode_head(struct list *list)
index 1704d8d37ede6e3ace8375ff87cb22e410c77aae..90997348cf3ab3bdf129abe9541fc6cb27a2882c 100644 (file)
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -89,6 +89,35 @@ struct pbr_rule {
        uint32_t ifindex;
 };
 
+/* TCP flags value shared
+ * those are values of byte 13 of TCP header
+ * as mentioned in rfc793
+ */
+#define TCP_HEADER_FIN (0x01)
+#define TCP_HEADER_SYN (0x02)
+#define TCP_HEADER_RST (0x04)
+#define TCP_HEADER_PSH (0x08)
+#define TCP_HEADER_ACK (0x10)
+#define TCP_HEADER_URG (0x20)
+#define TCP_HEADER_ALL_FLAGS (TCP_HEADER_FIN | TCP_HEADER_SYN \
+                             | TCP_HEADER_RST | TCP_HEADER_PSH \
+                             | TCP_HEADER_ACK | TCP_HEADER_URG)
+
+/* Pbr IPTable defines
+ * those are common flags shared between BGP and Zebra
+ */
+#define MATCH_IP_SRC_SET               (1 << 0)
+#define MATCH_IP_DST_SET               (1 << 1)
+#define MATCH_PORT_SRC_SET             (1 << 2)
+#define MATCH_PORT_DST_SET             (1 << 3)
+#define MATCH_PORT_SRC_RANGE_SET       (1 << 4)
+#define MATCH_PORT_DST_RANGE_SET       (1 << 5)
+#define MATCH_DSCP_SET                 (1 << 6)
+#define MATCH_DSCP_INVERSE_SET         (1 << 7)
+#define MATCH_PKT_LEN_INVERSE_SET      (1 << 8)
+#define MATCH_FRAGMENT_INVERSE_SET     (1 << 9)
+#define MATCH_ICMP_SET                 (1 << 10)
+
 extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
                                struct pbr_rule *zrule);
 
index aba4c20166175e27049d126def18c4315e95e25e..a172eedc995256ee378e77fa23849259dbf4a53d 100644 (file)
@@ -1109,6 +1109,10 @@ struct stream_fifo *stream_fifo_new(void)
 /* Add new stream to fifo. */
 void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
 {
+#if defined DEV_BUILD
+       size_t max, curmax;
+#endif
+
        if (fifo->tail)
                fifo->tail->next = s;
        else
@@ -1116,8 +1120,15 @@ void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
 
        fifo->tail = s;
        fifo->tail->next = NULL;
-
+#if !defined DEV_BUILD
        atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
+#else
+       max = atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
+       curmax = atomic_load_explicit(&fifo->max_count, memory_order_relaxed);
+       if (max > curmax)
+               atomic_store_explicit(&fifo->max_count, max,
+                                     memory_order_relaxed);
+#endif
 }
 
 void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s)
index e5d325e43ed4940dd65f421d6152e60d892a9d81..11af85c663d086438a270f4879742f2c547eaef3 100644 (file)
@@ -115,6 +115,9 @@ struct stream_fifo {
 
        /* number of streams in this fifo */
        _Atomic size_t count;
+#if defined DEV_BUILD
+       _Atomic size_t max_count;
+#endif
 
        struct stream *head;
        struct stream *tail;
index e6111f9d7120e618f6a0c3471e8694bb2c482374..3bb0d8308ecbb94c1574eadbf57e7ca486985883 100644 (file)
@@ -287,6 +287,7 @@ static void vici_recv_sa(struct vici_conn *vici, struct zbuf *msg, int event)
        char buf[32];
        struct handle_sa_ctx ctx = {
                .event = event,
+               .msgctx.nsections = 0
        };
 
        vici_parse_message(vici, msg, parse_sa_message, &ctx.msgctx);
index 5398ea5054186f7a0ed8ac8173b402062e3fc8f7..7bccc78e00882fe4f93daea760c176f2e4eaeaa6 100644 (file)
@@ -161,9 +161,10 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
            && route->type != OSPF6_DEST_TYPE_RANGE
            && ((route->type != OSPF6_DEST_TYPE_ROUTER)
                || !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) {
-               if (is_debug)
-                       zlog_debug(
-                               "Route type is none of network, range nor ASBR, ignore");
+#if 0
+               zlog_debug(
+                       "Route type is none of network, range nor ASBR, ignore");
+#endif
                return 0;
        }
 
@@ -177,16 +178,17 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
 
        /* do not generate if the path's area is the same as target area */
        if (route->path.area_id == area->area_id) {
-               if (is_debug)
-                       zlog_debug("The route is in the area itself, ignore");
+#if 0
+               zlog_debug("The route is in the area itself, ignore");
+#endif
                return 0;
        }
 
        /* do not generate if the nexthops belongs to the target area */
        if (ospf6_abr_nexthops_belong_to_area(route, area)) {
-               if (is_debug)
-                       zlog_debug(
-                               "The route's nexthop is in the same area, ignore");
+#if 0
+               zlog_debug("The route's nexthop is in the same area, ignore");
+#endif
                return 0;
        }
 
@@ -869,7 +871,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
                                lsa->header);
                prefix.family = AF_INET6;
                prefix.prefixlen = prefix_lsa->prefix.prefix_length;
-               ospf6_prefix_in6_addr(&prefix.u.prefix6, &prefix_lsa->prefix);
+               ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
+                                     &prefix_lsa->prefix);
                if (is_debug)
                        prefix2str(&prefix, buf, sizeof(buf));
                table = oa->ospf6->route_table;
@@ -1289,7 +1292,7 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
                        (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
                                lsa->header);
 
-               ospf6_prefix_in6_addr(&in6, &prefix_lsa->prefix);
+               ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
                if (buf) {
                        inet_ntop(AF_INET6, &in6, buf, buflen);
                        sprintf(&buf[strlen(buf)], "/%d",
index 7f575ee50638b8e5da6c56add7fa7f4cc802a34c..a7233965077b03b703500a94bd13ac59cc89b0e5 100644 (file)
@@ -497,7 +497,8 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
        route->type = OSPF6_DEST_TYPE_NETWORK;
        route->prefix.family = AF_INET6;
        route->prefix.prefixlen = external->prefix.prefix_length;
-       ospf6_prefix_in6_addr(&route->prefix.u.prefix6, &external->prefix);
+       ospf6_prefix_in6_addr(&route->prefix.u.prefix6, external,
+                             &external->prefix);
 
        route->path.area_id = asbr_entry->path.area_id;
        route->path.origin.type = lsa->header->type;
@@ -576,7 +577,7 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
        route_to_del->type = OSPF6_DEST_TYPE_NETWORK;
        route_to_del->prefix.family = AF_INET6;
        route_to_del->prefix.prefixlen = external->prefix.prefix_length;
-       ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6,
+       ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6, external,
                              &external->prefix);
 
        route_to_del->path.origin.type = lsa->header->type;
@@ -603,7 +604,7 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
        memset(&prefix, 0, sizeof(struct prefix));
        prefix.family = AF_INET6;
        prefix.prefixlen = external->prefix.prefix_length;
-       ospf6_prefix_in6_addr(&prefix.u.prefix6, &external->prefix);
+       ospf6_prefix_in6_addr(&prefix.u.prefix6, external, &external->prefix);
 
        route = ospf6_route_lookup(&prefix, ospf6->route_table);
        if (route == NULL) {
@@ -1705,7 +1706,8 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
                        lsa->header);
 
                if (pos == 0) {
-                       ospf6_prefix_in6_addr(&in6, &external->prefix);
+                       ospf6_prefix_in6_addr(&in6, external,
+                                             &external->prefix);
                        prefix_length = external->prefix.prefix_length;
                } else {
                        in6 = *((struct in6_addr
index 7898b109050ee506cf5706f7fc0de091b4630590..0ce08a61e259b67e9fdde0fddfc6ea5dc6481299 100644 (file)
@@ -1700,7 +1700,8 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
                memset(&route->prefix, 0, sizeof(struct prefix));
                route->prefix.family = AF_INET6;
                route->prefix.prefixlen = op->prefix_length;
-               ospf6_prefix_in6_addr(&route->prefix.u.prefix6, op);
+               ospf6_prefix_in6_addr(&route->prefix.u.prefix6,
+                                     intra_prefix_lsa, op);
 
                route->type = OSPF6_DEST_TYPE_NETWORK;
                route->path.origin.type = lsa->header->type;
@@ -1882,7 +1883,7 @@ void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
                memset(&prefix, 0, sizeof(struct prefix));
                prefix.family = AF_INET6;
                prefix.prefixlen = op->prefix_length;
-               ospf6_prefix_in6_addr(&prefix.u.prefix6, op);
+               ospf6_prefix_in6_addr(&prefix.u.prefix6, intra_prefix_lsa, op);
 
                route = ospf6_route_lookup(&prefix, oa->route_table);
                if (route == NULL)
index 4b56a64b7f66803e9e788c3808316ccad5f356a2..864974c9a4c3d952723a1a9a6dede2e786c685ab 100644 (file)
 
 #include "ospf6_proto.h"
 
+void ospf6_prefix_in6_addr(struct in6_addr *in6, const void *prefix_buf,
+                          const struct ospf6_prefix *p)
+{
+       ptrdiff_t in6_off = (caddr_t)p->addr - (caddr_t)prefix_buf;
+
+       memset(in6, 0, sizeof(struct in6_addr));
+       memcpy(in6, (uint8_t *)prefix_buf + in6_off,
+              OSPF6_PREFIX_SPACE(p->prefix_length));
+}
+
 void ospf6_prefix_apply_mask(struct ospf6_prefix *op)
 {
        uint8_t *pnt, mask;
index ca2804c47624d52eeb7b0aa46ed1bc241f58fcb5..c9e7b549db8b4443cb99f86fb33c87b41ff11f44 100644 (file)
@@ -84,13 +84,8 @@ struct ospf6_prefix {
 #define OSPF6_PREFIX_NEXT(x)                                                   \
        ((struct ospf6_prefix *)((caddr_t)(x) + OSPF6_PREFIX_SIZE(x)))
 
-#define ospf6_prefix_in6_addr(in6, op)                                         \
-       do {                                                                   \
-               memset(in6, 0, sizeof(struct in6_addr));                       \
-               memcpy(in6, (caddr_t)(op) + sizeof(struct ospf6_prefix),       \
-                      OSPF6_PREFIX_SPACE((op)->prefix_length));               \
-       } while (0)
-
+extern void ospf6_prefix_in6_addr(struct in6_addr *in6, const void *prefix_buf,
+                                 const struct ospf6_prefix *p);
 extern void ospf6_prefix_apply_mask(struct ospf6_prefix *op);
 extern void ospf6_prefix_options_printbuf(uint8_t prefix_options, char *buf,
                                          int size);
index ae7f61c8eb1c2d9787ffa539946e3a47d2224b0a..cb384bfe1da8d2dd021f2c18a44c91df73d3d459 100644 (file)
@@ -737,8 +737,6 @@ static void pim_zebra_connected(struct zclient *zclient)
 
 void pim_zebra_init(void)
 {
-       int i;
-
        /* Socket for receiving updates from Zebra daemon */
        zclient = zclient_new_notify(master, &zclient_options_default);
 
@@ -754,31 +752,7 @@ void pim_zebra_init(void)
 
        zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
        if (PIM_DEBUG_PIM_TRACE) {
-               zlog_info("zclient_init cleared redistribution request");
-       }
-
-       /* Request all redistribution */
-       for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
-               if (i == zclient->redist_default)
-                       continue;
-               vrf_bitmap_set(zclient->redist[AFI_IP][i], pimg->vrf_id);
-               ;
-               if (PIM_DEBUG_PIM_TRACE) {
-                       zlog_debug("%s: requesting redistribution for %s (%i)",
-                                  __PRETTY_FUNCTION__, zebra_route_string(i),
-                                  i);
-               }
-       }
-
-       /* Request default information */
-       zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
-                                    pimg->vrf_id);
-
-       if (PIM_DEBUG_PIM_TRACE) {
-               zlog_info("%s: requesting default information redistribution",
-                         __PRETTY_FUNCTION__);
-
-               zlog_notice("%s: zclient update socket initialized",
+               zlog_notice("%s: zclient socket initialized",
                            __PRETTY_FUNCTION__);
        }
 
index 0697cd8b751811ae6568d20260d214edccb9e16c..b56eaa899f5fb7a2b55e13ff236fa34bc667f792 100644 (file)
@@ -3357,9 +3357,12 @@ static void vtysh_autocomplete(vector comps, struct cmd_token *token)
        snprintf(accmd, sizeof(accmd), "autocomplete %d %s %s", token->type,
                 token->text, token->varname ? token->varname : "-");
 
+       vty->of_saved = vty->of;
+       vty->of = NULL;
        for (i = 0; i < array_size(vtysh_client); i++)
                vtysh_client_run_all(&vtysh_client[i], accmd, 1, vtysh_ac_line,
                                     comps);
+       vty->of = vty->of_saved;
 }
 
 static const struct cmd_variable_handler vtysh_var_handler[] = {
index 7334c8094a3001c0bf4ccde57cb0ff43842c3b14..d9c663184531acb27f873f4ac1664bed917ceb93 100644 (file)
@@ -545,7 +545,6 @@ static void netlink_parse_extended_ack(struct nlmsghdr *h)
 
                if (off > h->nlmsg_len) {
                        zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS\n");
-                       off = 0;
                } else if (!(h->nlmsg_flags & NLM_F_CAPPED)) {
                        /*
                         * Header of failed message
index 853a83373dbdfdeeeb887977e999caacaa0eb755..6e0d86d668eeb5d251df638bd9f6fb17383841f8 100644 (file)
@@ -521,6 +521,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
        struct zapi_nexthop *api_nh;
        struct nexthop *nexthop;
        int count = 0;
+       afi_t afi;
 
        memset(&api, 0, sizeof(api));
        api.vrf_id = re->vrf_id;
@@ -528,6 +529,24 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
        api.instance = re->instance;
        api.flags = re->flags;
 
+       afi = family2afi(p->family);
+       switch (afi) {
+       case AFI_IP:
+               if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+                       client->redist_v4_add_cnt++;
+               else
+                       client->redist_v4_del_cnt++;
+               break;
+       case AFI_IP6:
+               if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+                       client->redist_v6_add_cnt++;
+               else
+                       client->redist_v6_del_cnt++;
+               break;
+       default:
+               break;
+       }
+
        /* Prefix. */
        api.prefix = *p;
        if (src_p) {
@@ -2896,9 +2915,9 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
 
                if (!is_default_prefix(&zpi.dst))
                        zpi.filter_bm |= PBR_FILTER_DST_IP;
-               if (zpi.dst_port_min != 0)
+               if (zpi.dst_port_min != 0 || zpi.proto == IPPROTO_ICMP)
                        zpi.filter_bm |= PBR_FILTER_DST_PORT;
-               if (zpi.src_port_min != 0)
+               if (zpi.src_port_min != 0 || zpi.proto == IPPROTO_ICMP)
                        zpi.filter_bm |= PBR_FILTER_SRC_PORT;
                if (zpi.dst_port_max != 0)
                        zpi.filter_bm |= PBR_FILTER_DST_PORT_RANGE;
@@ -2938,6 +2957,12 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS)
        STREAM_GETL(s, zpi.action);
        STREAM_GETL(s, zpi.fwmark);
        STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
+       STREAM_GETW(s, zpi.pkt_len_min);
+       STREAM_GETW(s, zpi.pkt_len_max);
+       STREAM_GETW(s, zpi.tcp_flags);
+       STREAM_GETW(s, zpi.tcp_mask_flags);
+       STREAM_GETC(s, zpi.dscp_value);
+       STREAM_GETC(s, zpi.fragment);
        STREAM_GETL(s, zpi.nb_interface);
        zebra_pbr_iptable_update_interfacelist(s, &zpi);
 
index 317b02f601139d4182f85c8a2c01c8cc2038f9ba..96e6df34da9c1514e3669716b44abc76927a3bad 100644 (file)
@@ -307,7 +307,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
                        nlh = (struct nlmsghdr *)((char *)nlh
                                                  + NETLINK_ALIGN(
                                                            nlh->nlmsg_len));
-               } while (len != 0 && return_nsid != NS_UNKNOWN && ret == 0);
+               } while (len != 0 && ret == 0);
        }
 
        close(fd);
index d511c8c6ec1479e4eb9d2262dad25b8107944afc..74ef25b031fb750c8dff6edeeab2b988d077fb48 100644 (file)
@@ -44,6 +44,63 @@ static const struct message ipset_type_msg[] = {
        {0}
 };
 
+const struct message icmp_typecode_str[] = {
+       { 0 << 8, "echo-reply"},
+       { 0 << 8, "pong"},
+       { 3 << 8, "network-unreachable"},
+       { (3 << 8) + 1, "host-unreachable"},
+       { (3 << 8) + 2, "protocol-unreachable"},
+       { (3 << 8) + 3, "port-unreachable"},
+       { (3 << 8) + 4, "fragmentation-needed"},
+       { (3 << 8) + 5, "source-route-failed"},
+       { (3 << 8) + 6, "network-unknown"},
+       { (3 << 8) + 7, "host-unknown"},
+       { (3 << 8) + 9, "network-prohibited"},
+       { (3 << 8) + 10, "host-prohibited"},
+       { (3 << 8) + 11, "TOS-network-unreachable"},
+       { (3 << 8) + 12, "TOS-host-unreachable"},
+       { (3 << 8) + 13, "communication-prohibited"},
+       { (3 << 8) + 14, "host-precedence-violation"},
+       { (3 << 8) + 15, "precedence-cutoff"},
+       { 4 << 8, "source-quench"},
+       { 5 << 8, "network-redirect"},
+       { (5 << 8) +  1, "host-redirect"},
+       { (5 << 8) +  2, "TOS-network-redirect"},
+       { (5 << 8) +  3, "TOS-host-redirect"},
+       { 8 << 8, "echo-request"},
+       { 8 << 8, "ping"},
+       { 9 << 8, "router-advertisement"},
+       { 10 << 8, "router-solicitation"},
+       { 11 << 8, "ttl-zero-during-transit"},
+       { (11 << 8) + 1, "ttl-zero-during-reassembly"},
+       { 12 << 8, "ip-header-bad"},
+       { (12 << 8) + 1, "required-option-missing"},
+       { 13 << 8, "timestamp-request"},
+       { 14 << 8, "timestamp-reply"},
+       { 17 << 8, "address-mask-request"},
+       { 18 << 8, "address-mask-reply"},
+       {0}
+};
+
+/* definitions */
+static const struct message tcp_value_str[] = {
+       {TCP_HEADER_FIN, "FIN"},
+       {TCP_HEADER_SYN, "SYN"},
+       {TCP_HEADER_RST, "RST"},
+       {TCP_HEADER_PSH, "PSH"},
+       {TCP_HEADER_ACK, "ACK"},
+       {TCP_HEADER_URG, "URG"},
+       {0}
+};
+
+static const struct message fragment_value_str[] = {
+       {1, "dont-fragment"},
+       {2, "is-fragment"},
+       {4, "first-fragment"},
+       {8, "last-fragment"},
+       {0}
+};
+
 /* static function declarations */
 DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns,
                                    struct zebra_pbr_ipset_entry *ipset,
@@ -322,6 +379,12 @@ uint32_t zebra_pbr_iptable_hash_key(void *arg)
        key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE,
                     0x63ab42de);
        key = jhash_1word(iptable->fwmark, key);
+       key = jhash_1word(iptable->pkt_len_min, key);
+       key = jhash_1word(iptable->pkt_len_max, key);
+       key = jhash_1word(iptable->tcp_flags, key);
+       key = jhash_1word(iptable->tcp_mask_flags, key);
+       key = jhash_1word(iptable->dscp_value, key);
+       key = jhash_1word(iptable->fragment, key);
        return jhash_3words(iptable->filter_bm, iptable->type,
                            iptable->unique, key);
 }
@@ -346,6 +409,18 @@ int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
        if (strncmp(r1->ipset_name, r2->ipset_name,
                    ZEBRA_IPSET_NAME_SIZE))
                return 0;
+       if (r1->pkt_len_min != r2->pkt_len_min)
+               return 0;
+       if (r1->pkt_len_max != r2->pkt_len_max)
+               return 0;
+       if (r1->tcp_flags != r2->tcp_flags)
+               return 0;
+       if (r1->tcp_mask_flags != r2->tcp_mask_flags)
+               return 0;
+       if (r1->dscp_value != r2->dscp_value)
+               return 0;
+       if (r1->fragment != r2->fragment)
+               return 0;
        return 1;
 }
 
@@ -515,7 +590,7 @@ struct pbr_ipset_name_lookup {
        char ipset_name[ZEBRA_IPSET_NAME_SIZE];
 };
 
-static const char *zebra_pbr_ipset_type2str(uint32_t type)
+const char *zebra_pbr_ipset_type2str(uint32_t type)
 {
        return lookup_msg(ipset_type_msg, type,
                          "Unrecognized IPset Type");
@@ -773,6 +848,30 @@ static const char *zebra_pbr_prefix2str(union prefixconstptr pu,
        return prefix2str(pu, str, size);
 }
 
+static void zebra_pbr_display_icmp(struct vty *vty,
+                                  struct zebra_pbr_ipset_entry *zpie)
+{
+       char decoded_str[20];
+       uint16_t port;
+
+       /* range icmp type */
+       if (zpie->src_port_max || zpie->dst_port_max) {
+               vty_out(vty, ":icmp:[type <%d:%d>;code <%d:%d>",
+                       zpie->src_port_min, zpie->src_port_max,
+                       zpie->dst_port_min, zpie->dst_port_max);
+       } else {
+               port = ((zpie->src_port_min << 8) & 0xff00) +
+                       (zpie->dst_port_min & 0xff);
+               memset(decoded_str, 0, sizeof(decoded_str));
+               sprintf(decoded_str, "%d/%d",
+                       zpie->src_port_min,
+                       zpie->dst_port_min);
+               vty_out(vty, ":icmp:%s",
+                       lookup_msg(icmp_typecode_str,
+                                  port, decoded_str));
+       }
+}
+
 static void zebra_pbr_display_port(struct vty *vty, uint32_t filter_bm,
                            uint16_t port_min, uint16_t port_max,
                            uint8_t proto)
@@ -816,7 +915,8 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
 
                zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
                vty_out(vty, "\tfrom %s", buf);
-               if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
+               if (zpie->filter_bm & PBR_FILTER_SRC_PORT &&
+                   zpie->proto != IPPROTO_ICMP)
                        zebra_pbr_display_port(vty, zpie->filter_bm,
                                               zpie->src_port_min,
                                               zpie->src_port_max,
@@ -824,11 +924,14 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
                vty_out(vty, " to ");
                zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
                vty_out(vty, "%s", buf);
-               if (zpie->filter_bm & PBR_FILTER_DST_PORT)
+               if (zpie->filter_bm & PBR_FILTER_DST_PORT &&
+                   zpie->proto != IPPROTO_ICMP)
                        zebra_pbr_display_port(vty, zpie->filter_bm,
                                               zpie->dst_port_min,
                                               zpie->dst_port_max,
                                               zpie->proto);
+               if (zpie->proto == IPPROTO_ICMP)
+                       zebra_pbr_display_icmp(vty, zpie);
        } else if ((zpi->type == IPSET_NET) ||
                   (zpi->type == IPSET_NET_PORT)) {
                char buf[PREFIX_STRLEN];
@@ -837,7 +940,8 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
                        zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
                        vty_out(vty, "\tfrom %s", buf);
                }
-               if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
+               if (zpie->filter_bm & PBR_FILTER_SRC_PORT &&
+                   zpie->proto != IPPROTO_ICMP)
                        zebra_pbr_display_port(vty, zpie->filter_bm,
                                               zpie->src_port_min,
                                               zpie->src_port_max,
@@ -846,11 +950,14 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
                        zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
                        vty_out(vty, "\tto %s", buf);
                }
-               if (zpie->filter_bm & PBR_FILTER_DST_PORT)
+               if (zpie->filter_bm & PBR_FILTER_DST_PORT &&
+                   zpie->proto != IPPROTO_ICMP)
                        zebra_pbr_display_port(vty, zpie->filter_bm,
                                               zpie->dst_port_min,
                                               zpie->dst_port_max,
                                               zpie->proto);
+               if (zpie->proto == IPPROTO_ICMP)
+                       zebra_pbr_display_icmp(vty, zpie);
        }
        vty_out(vty, " (%u)\n", zpie->unique);
 
@@ -882,6 +989,26 @@ static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg)
        return HASHWALK_CONTINUE;
 }
 
+size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len,
+                                  uint16_t tcp_val)
+{
+       size_t len_written = 0;
+       static struct message nt = {0};
+       const struct message *pnt;
+       int incr = 0;
+
+       for (pnt = tcp_value_str;
+            memcmp(pnt, &nt, sizeof(struct message)); pnt++)
+               if (pnt->key & tcp_val) {
+                       len_written += snprintf(buffer + len_written,
+                                               len - len_written,
+                                               "%s%s", incr ?
+                                               ",":"", pnt->str);
+                       incr++;
+               }
+       return len_written;
+}
+
 /*
  */
 void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname)
@@ -946,7 +1073,42 @@ static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg)
        vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name,
                iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect",
                iptable->unique);
-
+       if (iptable->pkt_len_min || iptable->pkt_len_max) {
+               if (!iptable->pkt_len_max)
+                       vty_out(vty, "\t pkt len %u\n",
+                               iptable->pkt_len_min);
+               else
+                       vty_out(vty, "\t pkt len [%u;%u]\n",
+                               iptable->pkt_len_min,
+                               iptable->pkt_len_max);
+       }
+       if (iptable->tcp_flags || iptable->tcp_mask_flags) {
+               char tcp_flag_str[64];
+               char tcp_flag_mask_str[64];
+
+               zebra_pbr_tcpflags_snprintf(tcp_flag_str,
+                                           sizeof(tcp_flag_str),
+                                           iptable->tcp_flags);
+               zebra_pbr_tcpflags_snprintf(tcp_flag_mask_str,
+                                           sizeof(tcp_flag_mask_str),
+                                           iptable->tcp_mask_flags);
+               vty_out(vty, "\t tcpflags [%s/%s]\n",
+                       tcp_flag_str, tcp_flag_mask_str);
+       }
+       if (iptable->filter_bm & (MATCH_DSCP_SET | MATCH_DSCP_INVERSE_SET)) {
+               vty_out(vty, "\t dscp %s %d\n",
+                       iptable->filter_bm & MATCH_DSCP_INVERSE_SET ?
+                       "not" : "", iptable->dscp_value);
+       }
+       if (iptable->fragment) {
+               char val_str[10];
+
+               sprintf(val_str, "%d", iptable->fragment);
+               vty_out(vty, "\t fragment%s %s\n",
+                       iptable->filter_bm & MATCH_FRAGMENT_INVERSE_SET ?
+                       " not" : "", lookup_msg(fragment_value_str,
+                                              iptable->fragment, val_str));
+       }
        ret = hook_call(zebra_pbr_iptable_wrap_script_get_stat,
                        zns, iptable, &pkts, &bytes);
        if (ret && pkts > 0)
index 6cbafd6daaed1dd771c41395d6e8fb40344c3e69..fd83502ae180e1f8982228b7a50c79474a7660ba 100644 (file)
@@ -91,8 +91,10 @@ struct zebra_pbr_ipset_entry {
        struct prefix src;
        struct prefix dst;
 
+       /* udp/tcp src port or icmp type */
        uint16_t src_port_min;
        uint16_t src_port_max;
+       /* udp/tcp dst port or icmp code */
        uint16_t dst_port_min;
        uint16_t dst_port_max;
 
@@ -131,6 +133,13 @@ struct zebra_pbr_iptable {
 
        uint32_t action;
 
+       uint16_t pkt_len_min;
+       uint16_t pkt_len_max;
+       uint16_t tcp_flags;
+       uint16_t tcp_mask_flags;
+       uint8_t dscp_value;
+       uint8_t fragment;
+
        uint32_t nb_interface;
 
        struct list *interface_name_list;
@@ -138,6 +147,10 @@ struct zebra_pbr_iptable {
        char ipset_name[ZEBRA_IPSET_NAME_SIZE];
 };
 
+extern const struct message icmp_typecode_str[];
+
+const char *zebra_pbr_ipset_type2str(uint32_t type);
+
 void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule);
 void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule);
 void zebra_pbr_create_ipset(struct zebra_ns *zns,
@@ -225,6 +238,8 @@ extern void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname);
 extern void zebra_pbr_show_iptable(struct vty *vty);
 extern void zebra_pbr_iptable_update_interfacelist(struct stream *s,
                                   struct zebra_pbr_iptable *zpi);
+size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len,
+                                  uint16_t tcp_val);
 
 DECLARE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns,
                                    struct zebra_pbr_ipset_entry *ipset,
index bd00823ed82d1c63d0228e10a02107141dd1dc94..8935956b2572f94a3e4d02a01ea9e63c4cd8a1c2 100644 (file)
@@ -1428,18 +1428,14 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
                                if (new != old)
                                        zlog_debug(
                                                "%u:%s: Deleting route rn %p, re %p (type %d) "
-                                               "old %p (type %d) - %s",
+                                               "old %p (type %d) - nexthop inactive",
                                                zvrf_id(zvrf), buf, rn, new,
-                                               new->type, old, old->type,
-                                               nh_active ? "install failed"
-                                                         : "nexthop inactive");
+                                               new->type, old, old->type);
                                else
                                        zlog_debug(
-                                               "%u:%s: Deleting route rn %p, re %p (type %d) - %s",
+                                               "%u:%s: Deleting route rn %p, re %p (type %d) - nexthop inactive",
                                                zvrf_id(zvrf), buf, rn, new,
-                                               new->type,
-                                               nh_active ? "install failed"
-                                                         : "nexthop inactive");
+                                               new->type);
                        }
 
                        /* If labeled-unicast route, uninstall transit LSP. */
index 14e0db40bfb50c62d864f14a30716af10b375e7d..b297f75ed943b4b5c2433650345d56fbf390bab6 100644 (file)
@@ -198,7 +198,7 @@ static int zserv_write(struct thread *thread)
 {
        struct zserv *client = THREAD_ARG(thread);
        struct stream *msg;
-       uint32_t wcmd;
+       uint32_t wcmd = 0;
        struct stream_fifo *cache;
 
        /* If we have any data pending, try to flush it first */
@@ -939,6 +939,11 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
        vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt);
        vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt);
 
+#if defined DEV_BUILD
+       vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
+               client->ibuf_fifo->count, client->ibuf_fifo->max_count,
+               client->obuf_fifo->count, client->obuf_fifo->max_count);
+#endif
        vty_out(vty, "\n");
        return;
 }