]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: handle configuration of iptables with zebra
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 12 Mar 2018 08:38:53 +0000 (09:38 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 30 Apr 2018 09:56:23 +0000 (11:56 +0200)
The API for filling in an IPTABLE_ADD and IPTABLE_DELETE message.
Also, the API is handling the notification callback, so as to know if
zebra managed to add or delete the relevant iptable entry.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
lib/zclient.c
lib/zclient.h

index eb9cc6c3f18c6c257389da5f1561681ec1237059..f476686037d1d63710909fccf932983c7f89087d 100644 (file)
@@ -2047,6 +2047,49 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient,
        return 0;
 }
 
+static int iptable_notify_owner(int command, struct zclient *zclient,
+                               zebra_size_t length, vrf_id_t vrf_id)
+{
+       uint32_t unique;
+       enum zapi_iptable_notify_owner note;
+       struct bgp_pbr_match *bgpm;
+
+       if (!zapi_iptable_notify_decode(
+                                       zclient->ibuf,
+                                       &unique,
+                                       &note))
+               return -1;
+       bgpm = bgp_pbr_match_iptable_lookup(vrf_id, unique);
+       if (!bgpm) {
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: Fail to look BGP iptable (%u)",
+                                  __PRETTY_FUNCTION__, unique);
+               return 0;
+       }
+       switch (note) {
+       case ZAPI_IPTABLE_FAIL_INSTALL:
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: Received IPTABLE_FAIL_INSTALL",
+                                  __PRETTY_FUNCTION__);
+               bgpm->installed_in_iptable = false;
+               bgpm->install_iptable_in_progress = false;
+               break;
+       case ZAPI_IPTABLE_INSTALLED:
+               bgpm->installed_in_iptable = true;
+               bgpm->install_iptable_in_progress = false;
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: Received IPTABLE_INSTALLED",
+                                  __PRETTY_FUNCTION__);
+               break;
+       case ZAPI_IPTABLE_REMOVED:
+               if (BGP_DEBUG(zebra, ZEBRA))
+                       zlog_debug("%s: Received IPTABLE REMOVED",
+                                  __PRETTY_FUNCTION__);
+               break;
+       }
+       return 0;
+}
+
 static void bgp_encode_pbr_rule_action(struct stream *s,
                                  struct bgp_pbr_action *pbra)
 {
@@ -2107,6 +2150,29 @@ static void bgp_encode_pbr_ipset_entry_match(struct stream *s,
        stream_put(s, &pbime->dst.u.prefix, prefix_blen(&pbime->dst));
 }
 
+static void bgp_encode_pbr_iptable_match(struct stream *s,
+                                        struct bgp_pbr_action *bpa,
+                                        struct bgp_pbr_match *pbm)
+{
+       stream_putl(s, pbm->unique2);
+
+       stream_putl(s, pbm->type);
+
+       stream_putl(s, pbm->flags);
+
+       /* TODO: correlate with what is contained
+        * into bgp_pbr_action.
+        * currently only forward supported
+        */
+       if (bpa->nh.type == NEXTHOP_TYPE_BLACKHOLE)
+               stream_putl(s, ZEBRA_IPTABLES_DROP);
+       else
+               stream_putl(s, ZEBRA_IPTABLES_FORWARD);
+       stream_putl(s, bpa->fwmark);
+       stream_put(s, pbm->ipset_name,
+                  ZEBRA_IPSET_NAME_SIZE);
+}
+
 /* BGP has established connection with Zebra. */
 static void bgp_zebra_connected(struct zclient *zclient)
 {
@@ -2369,6 +2435,7 @@ void bgp_zebra_init(struct thread_master *master)
        zclient->rule_notify_owner = rule_notify_owner;
        zclient->ipset_notify_owner = ipset_notify_owner;
        zclient->ipset_entry_notify_owner = ipset_entry_notify_owner;
+       zclient->iptable_notify_owner = iptable_notify_owner;
 }
 
 void bgp_zebra_destroy(void)
@@ -2459,3 +2526,28 @@ void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime,
        if (!zclient_send_message(zclient) && install)
                pbrime->install_in_progress = true;
 }
+
+void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
+                         struct bgp_pbr_match *pbm,
+                         bool install)
+{
+       struct stream *s;
+
+       if (pbm->install_iptable_in_progress)
+               return;
+       zlog_debug("%s: name %s type %d mark %d %d", __PRETTY_FUNCTION__,
+                  pbm->ipset_name, pbm->type, pba->fwmark, install);
+       s = zclient->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s,
+                             install ? ZEBRA_IPTABLE_ADD :
+                             ZEBRA_IPTABLE_DELETE,
+                             VRF_DEFAULT);
+
+       bgp_encode_pbr_iptable_match(s, pba, pbm);
+
+       stream_putw_at(s, 0, stream_get_endp(s));
+       if (!zclient_send_message(zclient) && install)
+               pbm->install_iptable_in_progress = true;
+}
index 94a20a3fd1865b92e795f201e9753e226e5fe8ba..003db65318bb46e02a0a4dd50e7db74292da3efe 100644 (file)
@@ -79,5 +79,8 @@ extern void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim,
                                     bool install);
 extern void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime,
                                    bool install);
+extern void bgp_send_pbr_iptable(struct bgp_pbr_action *pba,
+                         struct bgp_pbr_match *pbm,
+                         bool install);
 
 #endif /* _QUAGGA_BGP_ZEBRA_H */
index dc27cbef701bfcdd9b747088b38b8932a6f23a30..cb39099fc21871971e82d2328f3c67627960b6d1 100644 (file)
@@ -1374,6 +1374,26 @@ stream_failure:
        return false;
 }
 
+bool zapi_iptable_notify_decode(struct stream *s,
+               uint32_t *unique,
+               enum zapi_iptable_notify_owner *note)
+{
+       uint32_t uni;
+
+       STREAM_GET(note, s, sizeof(*note));
+
+       STREAM_GETL(s, uni);
+
+       if (zclient_debug)
+               zlog_debug("%s: %u", __PRETTY_FUNCTION__, uni);
+       *unique = uni;
+
+       return true;
+
+stream_failure:
+       return false;
+}
+
 struct nexthop *nexthop_from_zapi_nexthop(struct zapi_nexthop *znh)
 {
        struct nexthop *n = nexthop_new();
@@ -2765,6 +2785,22 @@ static int zclient_read(struct thread *thread)
                        (*zclient->label_chunk)(command, zclient, length,
                                                      vrf_id);
                break;
+       case ZEBRA_IPSET_NOTIFY_OWNER:
+               if (zclient->ipset_notify_owner)
+                       (*zclient->ipset_notify_owner)(command, zclient, length,
+                                                     vrf_id);
+               break;
+       case ZEBRA_IPSET_ENTRY_NOTIFY_OWNER:
+               if (zclient->ipset_entry_notify_owner)
+                       (*zclient->ipset_entry_notify_owner)(command,
+                                                    zclient, length,
+                                                    vrf_id);
+               break;
+       case ZEBRA_IPTABLE_NOTIFY_OWNER:
+               if (zclient->iptable_notify_owner)
+                       (*zclient->iptable_notify_owner)(command,
+                                                zclient, length,
+                                                vrf_id);
        default:
                break;
        }
index 71f5b383843bb39155609de6e7149a70d0654a6d..8d26b7fe598b7919f1313f3dabca44047461c583 100644 (file)
@@ -258,6 +258,10 @@ struct zclient {
                                       struct zclient *zclient,
                                       uint16_t length,
                                       vrf_id_t vrf_id);
+       int (*iptable_notify_owner)(int command,
+                                   struct zclient *zclient,
+                                   uint16_t length,
+                                   vrf_id_t vrf_id);
 };
 
 /* Zebra API message flag. */
@@ -680,6 +684,9 @@ bool zapi_ipset_entry_notify_decode(struct stream *s,
            uint32_t *unique,
            char *ipset_name,
            enum zapi_ipset_entry_notify_owner *note);
+bool zapi_iptable_notify_decode(struct stream *s,
+               uint32_t *unique,
+               enum zapi_iptable_notify_owner *note);
 
 extern struct nexthop *nexthop_from_zapi_nexthop(struct zapi_nexthop *znh);
 extern bool zapi_nexthop_update_decode(struct stream *s,