diff mbox series

[ovs-dev,v3] binding.c: update ld->peers when lsp type updated

Message ID 20220816105632.220502-1-mheib@redhat.com
State Accepted
Headers show
Series [ovs-dev,v3] binding.c: update ld->peers when lsp type updated | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes success github build: passed

Commit Message

Mohammad Heib Aug. 16, 2022, 10:56 a.m. UTC
The local_datapath->peer_ports list contains peers pointers
to lsp<-->lrp ports that are supposed to be router end ports,
those pointers are added and deleted to the  local_datapath->peer_ports
when logical switch port of type router are added or deleted from the database.

The deletion and creation of those ports are handled very well when the LSP type
is a router, but if in any case, the user has changed the LSP type from router
port to any other LSP type the ld->peer_ports will keep pointing to this port
and if it was deleted it will keep pointing to invalid memory regions and that
could lead to invalid memory access in the ovn-controller.

To solve the above issue this patch will update the local_dataoath->peer_ports
whenever a lport is updated.

Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078
Co-authored-by: Xavier Simonart <xsimonar@redhat.com>
Signed-off-by: Mohammad Heib <mheib@redhat.com>
Signed-off-by: Xavier Simonart <xsimonar@redhat.com>
Signed-off-by: Mohammad Heib <mheib@redhat.com>
---
 controller/binding.c | 37 +++++++++++++++++++++++++++++++++++++
 tests/ovn.at         | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

Comments

Ales Musil Aug. 17, 2022, 8:04 a.m. UTC | #1
On Tue, Aug 16, 2022 at 12:57 PM Mohammad Heib <mheib@redhat.com> wrote:

> The local_datapath->peer_ports list contains peers pointers
> to lsp<-->lrp ports that are supposed to be router end ports,
> those pointers are added and deleted to the  local_datapath->peer_ports
> when logical switch port of type router are added or deleted from the
> database.
>
> The deletion and creation of those ports are handled very well when the
> LSP type
> is a router, but if in any case, the user has changed the LSP type from
> router
> port to any other LSP type the ld->peer_ports will keep pointing to this
> port
> and if it was deleted it will keep pointing to invalid memory regions and
> that
> could lead to invalid memory access in the ovn-controller.
>
> To solve the above issue this patch will update the
> local_dataoath->peer_ports
> whenever a lport is updated.
>
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078
> Co-authored-by: Xavier Simonart <xsimonar@redhat.com>
> Signed-off-by: Mohammad Heib <mheib@redhat.com>
> Signed-off-by: Xavier Simonart <xsimonar@redhat.com>
> Signed-off-by: Mohammad Heib <mheib@redhat.com>
> ---
>  controller/binding.c | 37 +++++++++++++++++++++++++++++++++++++
>  tests/ovn.at         | 37 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 74 insertions(+)
>
> diff --git a/controller/binding.c b/controller/binding.c
> index 9f5393a92..1221419a9 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -566,6 +566,39 @@ remove_related_lport(const struct sbrec_port_binding
> *pb,
>      }
>  }
>
> +/*
> + * Update local_datapath peers when port type changed
> + * and remove irrelevant ports from this list.
> + */
> +static void
> +update_ld_peers(const struct sbrec_port_binding *pb,
> +                 struct hmap *local_datapaths)
> +{
> +    struct local_datapath *ld =
> +        get_local_datapath(local_datapaths, pb->datapath->tunnel_key);
> +
> +    if (!ld) {
> +        return;
> +    }
> +
> +    /*
> +     * This will handle cases where the pb type was explicitly
> +     * changed from router type to any other port type and will
> +     * remove it from the ld peers list.
> +     */
> +    enum en_lport_type type = get_lport_type(pb);
> +    int num_peers = ld->n_peer_ports;
> +    if (type != LP_PATCH) {
> +        remove_local_datapath_peer_port(pb, ld, local_datapaths);
> +        if (num_peers != ld->n_peer_ports) {
> +            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> +            VLOG_DBG_RL(&rl,
> +                        "removing lport %s from the ld peers list",
> +                        pb->logical_port);
> +        }
> +    }
> +}
> +
>  static void
>  delete_active_pb_ras_pd(const struct sbrec_port_binding *pb,
>                          struct shash *ras_pd_map)
> @@ -2585,6 +2618,10 @@ handle_updated_port(struct binding_ctx_in *b_ctx_in,
>          return true;
>      }
>
> +    if (sbrec_port_binding_is_updated(pb, SBREC_PORT_BINDING_COL_TYPE)) {
> +        update_ld_peers(pb, b_ctx_out->local_datapaths);
> +    }
> +
>      update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd,
>                              "ipv6_prefix_delegation");
>
> diff --git a/tests/ovn.at b/tests/ovn.at
> index c8cc8cde4..79eda21d3 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -32404,3 +32404,40 @@ AT_CHECK([test $(ovn-sbctl list fdb | grep -c
> "00:00:00:00:10:30") = 0])
>  OVN_CLEANUP([hv1])
>  AT_CLEANUP
>  ])
> +
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([router port type update and then remove])
> +ovn_start
> +net_add n1
> +
> +sim_add hv1
> +as hv1
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.1
> +ovs-vsctl -- add-port br-int hv1-vif1 -- \
> +    set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
> +    options:tx_pcap=hv1/vif1-tx.pcap \
> +    options:rxq_pcap=hv1/vif1-rx.pcap \
> +    ofport-request=1
> +
> +check ovn-nbctl ls-add sw0
> +check ovn-nbctl lr-add ro0
> +check ovn-nbctl lsp-add sw0 sw0-p1
> +check ovn-nbctl lsp-add sw0 lsp
> +check ovn-nbctl lsp-set-type lsp router
> +check ovn-nbctl lsp-set-options lsp router-port=lrp
> +check ovn-nbctl lsp-set-addresses lsp  00:00:00:00:00:1
> +check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1 aef0:0:0:0:0:0:0:1/64
> +check ovn-nbctl set Logical_Router_Port lrp
> ipv6_ra_configs:send_periodic=true \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:address_mode=slaac
> \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:max_interval=2 \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:min_interval=1
> +check ovn-nbctl lsp-set-type lsp localnet
> +check ovn-nbctl --wait=hv sync
> +check ovn-nbctl lsp-del lsp
> +check ovn-nbctl lrp-del lrp
> +check ovn-nbctl --wait=hv sync
> +OVN_CLEANUP([hv1])
> +AT_CLEANUP
> +])
> --
> 2.34.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Thanks!

Acked-by: Ales Musil <amusil@redhat.com>
Mark Michelson Aug. 18, 2022, 6:18 p.m. UTC | #2
Hi Mohammad. The code changes look good, but I'm a bit confused about 
what the test case is intending to prove. It updates the type of the 
LSP, but there is no check to ensure that the change was successful, as 
far as I can tell.

On 8/16/22 06:56, Mohammad Heib wrote:
> The local_datapath->peer_ports list contains peers pointers
> to lsp<-->lrp ports that are supposed to be router end ports,
> those pointers are added and deleted to the  local_datapath->peer_ports
> when logical switch port of type router are added or deleted from the database.
> 
> The deletion and creation of those ports are handled very well when the LSP type
> is a router, but if in any case, the user has changed the LSP type from router
> port to any other LSP type the ld->peer_ports will keep pointing to this port
> and if it was deleted it will keep pointing to invalid memory regions and that
> could lead to invalid memory access in the ovn-controller.
> 
> To solve the above issue this patch will update the local_dataoath->peer_ports
> whenever a lport is updated.
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078
> Co-authored-by: Xavier Simonart <xsimonar@redhat.com>
> Signed-off-by: Mohammad Heib <mheib@redhat.com>
> Signed-off-by: Xavier Simonart <xsimonar@redhat.com>
> Signed-off-by: Mohammad Heib <mheib@redhat.com>
> ---
>   controller/binding.c | 37 +++++++++++++++++++++++++++++++++++++
>   tests/ovn.at         | 37 +++++++++++++++++++++++++++++++++++++
>   2 files changed, 74 insertions(+)
> 
> diff --git a/controller/binding.c b/controller/binding.c
> index 9f5393a92..1221419a9 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -566,6 +566,39 @@ remove_related_lport(const struct sbrec_port_binding *pb,
>       }
>   }
>   
> +/*
> + * Update local_datapath peers when port type changed
> + * and remove irrelevant ports from this list.
> + */
> +static void
> +update_ld_peers(const struct sbrec_port_binding *pb,
> +                 struct hmap *local_datapaths)
> +{
> +    struct local_datapath *ld =
> +        get_local_datapath(local_datapaths, pb->datapath->tunnel_key);
> +
> +    if (!ld) {
> +        return;
> +    }
> +
> +    /*
> +     * This will handle cases where the pb type was explicitly
> +     * changed from router type to any other port type and will
> +     * remove it from the ld peers list.
> +     */
> +    enum en_lport_type type = get_lport_type(pb);
> +    int num_peers = ld->n_peer_ports;
> +    if (type != LP_PATCH) {
> +        remove_local_datapath_peer_port(pb, ld, local_datapaths);
> +        if (num_peers != ld->n_peer_ports) {
> +            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> +            VLOG_DBG_RL(&rl,
> +                        "removing lport %s from the ld peers list",
> +                        pb->logical_port);
> +        }
> +    }
> +}
> +
>   static void
>   delete_active_pb_ras_pd(const struct sbrec_port_binding *pb,
>                           struct shash *ras_pd_map)
> @@ -2585,6 +2618,10 @@ handle_updated_port(struct binding_ctx_in *b_ctx_in,
>           return true;
>       }
>   
> +    if (sbrec_port_binding_is_updated(pb, SBREC_PORT_BINDING_COL_TYPE)) {
> +        update_ld_peers(pb, b_ctx_out->local_datapaths);
> +    }
> +
>       update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd,
>                               "ipv6_prefix_delegation");
>   
> diff --git a/tests/ovn.at b/tests/ovn.at
> index c8cc8cde4..79eda21d3 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -32404,3 +32404,40 @@ AT_CHECK([test $(ovn-sbctl list fdb | grep -c "00:00:00:00:10:30") = 0])
>   OVN_CLEANUP([hv1])
>   AT_CLEANUP
>   ])
> +
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([router port type update and then remove])
> +ovn_start
> +net_add n1
> +
> +sim_add hv1
> +as hv1
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.1
> +ovs-vsctl -- add-port br-int hv1-vif1 -- \
> +    set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
> +    options:tx_pcap=hv1/vif1-tx.pcap \
> +    options:rxq_pcap=hv1/vif1-rx.pcap \
> +    ofport-request=1
> +
> +check ovn-nbctl ls-add sw0
> +check ovn-nbctl lr-add ro0
> +check ovn-nbctl lsp-add sw0 sw0-p1
> +check ovn-nbctl lsp-add sw0 lsp
> +check ovn-nbctl lsp-set-type lsp router
> +check ovn-nbctl lsp-set-options lsp router-port=lrp
> +check ovn-nbctl lsp-set-addresses lsp  00:00:00:00:00:1
> +check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1 aef0:0:0:0:0:0:0:1/64
> +check ovn-nbctl set Logical_Router_Port lrp ipv6_ra_configs:send_periodic=true \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:address_mode=slaac \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:max_interval=2 \
> +        -- set Logical_Router_Port lrp ipv6_ra_configs:min_interval=1
> +check ovn-nbctl lsp-set-type lsp localnet
> +check ovn-nbctl --wait=hv sync
> +check ovn-nbctl lsp-del lsp
> +check ovn-nbctl lrp-del lrp
> +check ovn-nbctl --wait=hv sync
> +OVN_CLEANUP([hv1])
> +AT_CLEANUP
> +])
Mohammad Heib Aug. 18, 2022, 6:58 p.m. UTC | #3
Hi Mark,
Thank you for reviewing the patch.
actually, the test here is less interested in the type update but more in
the LSP deletion from the ld->peer_ports list
i don't have a way to see if the ld->n_peer_ports updated properly from the
tests units  when we change the port type, but i know that
if something wrong happens in the ovn-controller and ld->peer_ports keeps
pointing to the deleted LSP( which is what this patch
comes to fix ) the command* "check ovn-nbctl lrp-del lrp"* will cause some
invalid memory access and that will lead to a core dump in the
ovn-controller
and then the test case will fail with dump in the ovn-controller logs.
i know it is a bad way to test it like that but as i mentioned i don't have
a way to see the content of ld->peer_ports from the test :(.

see comments in the tests below.

On Thu, Aug 18, 2022 at 9:18 PM Mark Michelson <mmichels@redhat.com> wrote:

> Hi Mohammad. The code changes look good, but I'm a bit confused about
> what the test case is intending to prove. It updates the type of the
> LSP, but there is no check to ensure that the change was successful, as
> far as I can tell.
>


>
> On 8/16/22 06:56, Mohammad Heib wrote:
> > The local_datapath->peer_ports list contains peers pointers
> > to lsp<-->lrp ports that are supposed to be router end ports,
> > those pointers are added and deleted to the  local_datapath->peer_ports
> > when logical switch port of type router are added or deleted from the
> database.
> >
> > The deletion and creation of those ports are handled very well when the
> LSP type
> > is a router, but if in any case, the user has changed the LSP type from
> router
> > port to any other LSP type the ld->peer_ports will keep pointing to this
> port
> > and if it was deleted it will keep pointing to invalid memory regions
> and that
> > could lead to invalid memory access in the ovn-controller.
> >
> > To solve the above issue this patch will update the
> local_dataoath->peer_ports
> > whenever a lport is updated.
> >
> > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078
> > Co-authored-by: Xavier Simonart <xsimonar@redhat.com>
> > Signed-off-by: Mohammad Heib <mheib@redhat.com>
> > Signed-off-by: Xavier Simonart <xsimonar@redhat.com>
> > Signed-off-by: Mohammad Heib <mheib@redhat.com>
> > ---
> >   controller/binding.c | 37 +++++++++++++++++++++++++++++++++++++
> >   tests/ovn.at         | 37 +++++++++++++++++++++++++++++++++++++
> >   2 files changed, 74 insertions(+)
> >
> > diff --git a/controller/binding.c b/controller/binding.c
> > index 9f5393a92..1221419a9 100644
> > --- a/controller/binding.c
> > +++ b/controller/binding.c
> > @@ -566,6 +566,39 @@ remove_related_lport(const struct
> sbrec_port_binding *pb,
> >       }
> >   }
> >
> > +/*
> > + * Update local_datapath peers when port type changed
> > + * and remove irrelevant ports from this list.
> > + */
> > +static void
> > +update_ld_peers(const struct sbrec_port_binding *pb,
> > +                 struct hmap *local_datapaths)
> > +{
> > +    struct local_datapath *ld =
> > +        get_local_datapath(local_datapaths, pb->datapath->tunnel_key);
> > +
> > +    if (!ld) {
> > +        return;
> > +    }
> > +
> > +    /*
> > +     * This will handle cases where the pb type was explicitly
> > +     * changed from router type to any other port type and will
> > +     * remove it from the ld peers list.
> > +     */
> > +    enum en_lport_type type = get_lport_type(pb);
> > +    int num_peers = ld->n_peer_ports;
> > +    if (type != LP_PATCH) {
> > +        remove_local_datapath_peer_port(pb, ld, local_datapaths);
> > +        if (num_peers != ld->n_peer_ports) {
> > +            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1,
> 5);
> > +            VLOG_DBG_RL(&rl,
> > +                        "removing lport %s from the ld peers list",
> > +                        pb->logical_port);
> > +        }
> > +    }
> > +}
> > +
> >   static void
> >   delete_active_pb_ras_pd(const struct sbrec_port_binding *pb,
> >                           struct shash *ras_pd_map)
> > @@ -2585,6 +2618,10 @@ handle_updated_port(struct binding_ctx_in
> *b_ctx_in,
> >           return true;
> >       }
> >
> > +    if (sbrec_port_binding_is_updated(pb, SBREC_PORT_BINDING_COL_TYPE))
> {
> > +        update_ld_peers(pb, b_ctx_out->local_datapaths);
> > +    }
> > +
> >       update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd,
> >                               "ipv6_prefix_delegation");
> >
> > diff --git a/tests/ovn.at b/tests/ovn.at
> > index c8cc8cde4..79eda21d3 100644
> > --- a/tests/ovn.at
> > +++ b/tests/ovn.at
> > @@ -32404,3 +32404,40 @@ AT_CHECK([test $(ovn-sbctl list fdb | grep -c
> "00:00:00:00:10:30") = 0])
> >   OVN_CLEANUP([hv1])
> >   AT_CLEANUP
> >   ])
> > +
> > +OVN_FOR_EACH_NORTHD([
> > +AT_SETUP([router port type update and then remove])
> > +ovn_start
> > +net_add n1
> > +
> > +sim_add hv1
> > +as hv1
> > +ovs-vsctl add-br br-phys
> > +ovn_attach n1 br-phys 192.168.0.1
> > +ovs-vsctl -- add-port br-int hv1-vif1 -- \
> > +    set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
> > +    options:tx_pcap=hv1/vif1-tx.pcap \
> > +    options:rxq_pcap=hv1/vif1-rx.pcap \
> > +    ofport-request=1
> > +
> > +check ovn-nbctl ls-add sw0
> > +check ovn-nbctl lr-add ro0
> > +check ovn-nbctl lsp-add sw0 sw0-p1
> > +check ovn-nbctl lsp-add sw0 lsp
> > +check ovn-nbctl lsp-set-type lsp router
> > +check ovn-nbctl lsp-set-options lsp router-port=lrp
> > +check ovn-nbctl lsp-set-addresses lsp  00:00:00:00:00:1
> > +check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1 aef0:0:0:0:0:0:0:1/64
> > +check ovn-nbctl set Logical_Router_Port lrp
> ipv6_ra_configs:send_periodic=true \
> > +        -- set Logical_Router_Port lrp
> ipv6_ra_configs:address_mode=slaac \
> > +        -- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 \
> > +        -- set Logical_Router_Port lrp ipv6_ra_configs:max_interval=2 \
> > +        -- set Logical_Router_Port lrp ipv6_ra_configs:min_interval=1
>


> > +check ovn-nbctl lsp-set-type lsp localnet           <--------------
> this will delete the lsp from the ld->peer_ports and will delete its peer
> lrp  from the same list
>
> +check ovn-nbctl --wait=hv sync
> > +check ovn-nbctl lsp-del lsp                              <---------
> normall LSP deletion ( without this patch the ld->peer_ports will keeps
> pointing to deleted LSP invalid memory area)
>
> +check ovn-nbctl lrp-del lrp                              <---------
> noremal LRP deletions
> > +check ovn-nbctl --wait=hv sync
> > +OVN_CLEANUP([hv1])
> > +AT_CLEANUP
> > +])
>
> thanks
Mark Michelson Aug. 19, 2022, 3:04 p.m. UTC | #4
OK, thanks for the explanation, Mohammad. I added the following comment 
to the test to explain what is being tested.

     # The below commands change the LSP from "router" type in order to 
ensure that
     # no incorrect memory accesses occur. The test passes because there 
is no crash
     # in ovn-controller.

I added my Ack and pushed the change to branch-22.03, branch-22.06, and 
main.

On 8/18/22 14:58, Mohammad Heib wrote:
> Hi Mark,
> Thank you for reviewing the patch.
> actually, the test here is less interested in the type update but more 
> in the LSP deletion from theld->peer_ports list
> i don't have a way to see if theld->n_peer_portsupdated properly from 
> the tests units  when we change the port type, but i know that
> if something wrong happens in the ovn-controller and ld->peer_ports 
> keeps pointing to the deleted LSP( which is what this patch
> comes to fix ) the command*"check ovn-nbctl lrp-del lrp"* will cause 
> some invalid memory access and that will lead to a core dump in the 
> ovn-controller
> and then the test case will fail with dump in the ovn-controller logs.
> i know it is a bad way to test it like that but as i mentioned i don't 
> have a way to see the content of ld->peer_ports from the test :(.
> 
> see comments in the tests below.
> 
> On Thu, Aug 18, 2022 at 9:18 PM Mark Michelson <mmichels@redhat.com 
> <mailto:mmichels@redhat.com>> wrote:
> 
>     Hi Mohammad. The code changes look good, but I'm a bit confused about
>     what the test case is intending to prove. It updates the type of the
>     LSP, but there is no check to ensure that the change was successful, as
>     far as I can tell.
> 
> 
>     On 8/16/22 06:56, Mohammad Heib wrote:
>      > The local_datapath->peer_ports list contains peers pointers
>      > to lsp<-->lrp ports that are supposed to be router end ports,
>      > those pointers are added and deleted to the 
>     local_datapath->peer_ports
>      > when logical switch port of type router are added or deleted from
>     the database.
>      >
>      > The deletion and creation of those ports are handled very well
>     when the LSP type
>      > is a router, but if in any case, the user has changed the LSP
>     type from router
>      > port to any other LSP type the ld->peer_ports will keep pointing
>     to this port
>      > and if it was deleted it will keep pointing to invalid memory
>     regions and that
>      > could lead to invalid memory access in the ovn-controller.
>      >
>      > To solve the above issue this patch will update the
>     local_dataoath->peer_ports
>      > whenever a lport is updated.
>      >
>      > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2077078
>     <https://bugzilla.redhat.com/show_bug.cgi?id=2077078>
>      > Co-authored-by: Xavier Simonart <xsimonar@redhat.com
>     <mailto:xsimonar@redhat.com>>
>      > Signed-off-by: Mohammad Heib <mheib@redhat.com
>     <mailto:mheib@redhat.com>>
>      > Signed-off-by: Xavier Simonart <xsimonar@redhat.com
>     <mailto:xsimonar@redhat.com>>
>      > Signed-off-by: Mohammad Heib <mheib@redhat.com
>     <mailto:mheib@redhat.com>>
>      > ---
>      >   controller/binding.c | 37 +++++++++++++++++++++++++++++++++++++
>      >   tests/ovn.at <http://ovn.at>         | 37
>     +++++++++++++++++++++++++++++++++++++
>      >   2 files changed, 74 insertions(+)
>      >
>      > diff --git a/controller/binding.c b/controller/binding.c
>      > index 9f5393a92..1221419a9 100644
>      > --- a/controller/binding.c
>      > +++ b/controller/binding.c
>      > @@ -566,6 +566,39 @@ remove_related_lport(const struct
>     sbrec_port_binding *pb,
>      >       }
>      >   }
>      >
>      > +/*
>      > + * Update local_datapath peers when port type changed
>      > + * and remove irrelevant ports from this list.
>      > + */
>      > +static void
>      > +update_ld_peers(const struct sbrec_port_binding *pb,
>      > +                 struct hmap *local_datapaths)
>      > +{
>      > +    struct local_datapath *ld =
>      > +        get_local_datapath(local_datapaths,
>     pb->datapath->tunnel_key);
>      > +
>      > +    if (!ld) {
>      > +        return;
>      > +    }
>      > +
>      > +    /*
>      > +     * This will handle cases where the pb type was explicitly
>      > +     * changed from router type to any other port type and will
>      > +     * remove it from the ld peers list.
>      > +     */
>      > +    enum en_lport_type type = get_lport_type(pb);
>      > +    int num_peers = ld->n_peer_ports;
>      > +    if (type != LP_PATCH) {
>      > +        remove_local_datapath_peer_port(pb, ld, local_datapaths);
>      > +        if (num_peers != ld->n_peer_ports) {
>      > +            static struct vlog_rate_limit rl =
>     VLOG_RATE_LIMIT_INIT(1, 5);
>      > +            VLOG_DBG_RL(&rl,
>      > +                        "removing lport %s from the ld peers list",
>      > +                        pb->logical_port);
>      > +        }
>      > +    }
>      > +}
>      > +
>      >   static void
>      >   delete_active_pb_ras_pd(const struct sbrec_port_binding *pb,
>      >                           struct shash *ras_pd_map)
>      > @@ -2585,6 +2618,10 @@ handle_updated_port(struct binding_ctx_in
>     *b_ctx_in,
>      >           return true;
>      >       }
>      >
>      > +    if (sbrec_port_binding_is_updated(pb,
>     SBREC_PORT_BINDING_COL_TYPE)) {
>      > +        update_ld_peers(pb, b_ctx_out->local_datapaths);
>      > +    }
>      > +
>      >       update_active_pb_ras_pd(pb,
>     b_ctx_out->local_active_ports_ipv6_pd,
>      >                               "ipv6_prefix_delegation");
>      >
>      > diff --git a/tests/ovn.at <http://ovn.at> b/tests/ovn.at
>     <http://ovn.at>
>      > index c8cc8cde4..79eda21d3 100644
>      > --- a/tests/ovn.at <http://ovn.at>
>      > +++ b/tests/ovn.at <http://ovn.at>
>      > @@ -32404,3 +32404,40 @@ AT_CHECK([test $(ovn-sbctl list fdb |
>     grep -c "00:00:00:00:10:30") = 0])
>      >   OVN_CLEANUP([hv1])
>      >   AT_CLEANUP
>      >   ])
>      > +
>      > +OVN_FOR_EACH_NORTHD([
>      > +AT_SETUP([router port type update and then remove])
>      > +ovn_start
>      > +net_add n1
>      > +
>      > +sim_add hv1
>      > +as hv1
>      > +ovs-vsctl add-br br-phys
>      > +ovn_attach n1 br-phys 192.168.0.1
>      > +ovs-vsctl -- add-port br-int hv1-vif1 -- \
>      > +    set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
>      > +    options:tx_pcap=hv1/vif1-tx.pcap \
>      > +    options:rxq_pcap=hv1/vif1-rx.pcap \
>      > +    ofport-request=1
>      > +
>      > +check ovn-nbctl ls-add sw0
>      > +check ovn-nbctl lr-add ro0
>      > +check ovn-nbctl lsp-add sw0 sw0-p1
>      > +check ovn-nbctl lsp-add sw0 lsp
>      > +check ovn-nbctl lsp-set-type lsp router
>      > +check ovn-nbctl lsp-set-options lsp router-port=lrp
>      > +check ovn-nbctl lsp-set-addresses lsp  00:00:00:00:00:1
>      > +check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1
>     aef0:0:0:0:0:0:0:1/64
>      > +check ovn-nbctl set Logical_Router_Port lrp
>     ipv6_ra_configs:send_periodic=true \
>      > +        -- set Logical_Router_Port lrp
>     ipv6_ra_configs:address_mode=slaac \
>      > +        -- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 \
>      > +        -- set Logical_Router_Port lrp
>     ipv6_ra_configs:max_interval=2 \
>      > +        -- set Logical_Router_Port lrp
>     ipv6_ra_configs:min_interval=1
> 
>      > +check ovn-nbctl lsp-set-type lsp localnet          
>     <-------------- this will delete the lsp from the ld->peer_ports and
>     will delete its peer lrp  from the same list
> 
>      > +check ovn-nbctl --wait=hv sync
>      > +check ovn-nbctl lsp-del lsp                             
>     <--------- normall LSP deletion ( without this patch
>     theld->peer_ports will keeps pointing to deleted LSP invalid memory
>     area)
> 
>      > +check ovn-nbctl lrp-del lrp                             
>     <--------- noremal LRP deletions
>      > +check ovn-nbctl --wait=hv sync
>      > +OVN_CLEANUP([hv1])
>      > +AT_CLEANUP
>      > +])
> 
> thanks
diff mbox series

Patch

diff --git a/controller/binding.c b/controller/binding.c
index 9f5393a92..1221419a9 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -566,6 +566,39 @@  remove_related_lport(const struct sbrec_port_binding *pb,
     }
 }
 
+/*
+ * Update local_datapath peers when port type changed
+ * and remove irrelevant ports from this list.
+ */
+static void
+update_ld_peers(const struct sbrec_port_binding *pb,
+                 struct hmap *local_datapaths)
+{
+    struct local_datapath *ld =
+        get_local_datapath(local_datapaths, pb->datapath->tunnel_key);
+
+    if (!ld) {
+        return;
+    }
+
+    /*
+     * This will handle cases where the pb type was explicitly
+     * changed from router type to any other port type and will
+     * remove it from the ld peers list.
+     */
+    enum en_lport_type type = get_lport_type(pb);
+    int num_peers = ld->n_peer_ports;
+    if (type != LP_PATCH) {
+        remove_local_datapath_peer_port(pb, ld, local_datapaths);
+        if (num_peers != ld->n_peer_ports) {
+            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+            VLOG_DBG_RL(&rl,
+                        "removing lport %s from the ld peers list",
+                        pb->logical_port);
+        }
+    }
+}
+
 static void
 delete_active_pb_ras_pd(const struct sbrec_port_binding *pb,
                         struct shash *ras_pd_map)
@@ -2585,6 +2618,10 @@  handle_updated_port(struct binding_ctx_in *b_ctx_in,
         return true;
     }
 
+    if (sbrec_port_binding_is_updated(pb, SBREC_PORT_BINDING_COL_TYPE)) {
+        update_ld_peers(pb, b_ctx_out->local_datapaths);
+    }
+
     update_active_pb_ras_pd(pb, b_ctx_out->local_active_ports_ipv6_pd,
                             "ipv6_prefix_delegation");
 
diff --git a/tests/ovn.at b/tests/ovn.at
index c8cc8cde4..79eda21d3 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -32404,3 +32404,40 @@  AT_CHECK([test $(ovn-sbctl list fdb | grep -c "00:00:00:00:10:30") = 0])
 OVN_CLEANUP([hv1])
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([router port type update and then remove])
+ovn_start
+net_add n1
+
+sim_add hv1
+as hv1
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+ovs-vsctl -- add-port br-int hv1-vif1 -- \
+    set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
+    options:tx_pcap=hv1/vif1-tx.pcap \
+    options:rxq_pcap=hv1/vif1-rx.pcap \
+    ofport-request=1
+
+check ovn-nbctl ls-add sw0
+check ovn-nbctl lr-add ro0
+check ovn-nbctl lsp-add sw0 sw0-p1
+check ovn-nbctl lsp-add sw0 lsp
+check ovn-nbctl lsp-set-type lsp router
+check ovn-nbctl lsp-set-options lsp router-port=lrp
+check ovn-nbctl lsp-set-addresses lsp  00:00:00:00:00:1
+check ovn-nbctl lrp-add ro0 lrp 00:00:00:00:00:1 aef0:0:0:0:0:0:0:1/64
+check ovn-nbctl set Logical_Router_Port lrp ipv6_ra_configs:send_periodic=true \
+        -- set Logical_Router_Port lrp ipv6_ra_configs:address_mode=slaac \
+        -- set Logical_Router_Port lrp ipv6_ra_configs:mtu=1280 \
+        -- set Logical_Router_Port lrp ipv6_ra_configs:max_interval=2 \
+        -- set Logical_Router_Port lrp ipv6_ra_configs:min_interval=1
+check ovn-nbctl lsp-set-type lsp localnet
+check ovn-nbctl --wait=hv sync
+check ovn-nbctl lsp-del lsp
+check ovn-nbctl lrp-del lrp
+check ovn-nbctl --wait=hv sync
+OVN_CLEANUP([hv1])
+AT_CLEANUP
+])