On Mon, Apr 11, 2022 at 03:33:38PM +0800, Hangbin Liu wrote:
> Latest Linux kernel has supported getting PHC from bond directly. This
> would help topology like VLAN over bond to get PHC natively. To achieve
> this, the new hwtstamp flag is needed when passing hwtstamp_config to
> kernel. Let's supply the flag first, and fall back without flag if user
> run on old kernel.
> 
> Split port_change_phc() from function port_link_status() so the event
> functions could call it directly when find the phc changed.

I can follow this version better, thanks for that.

This refactoring...

> @@ -2636,10 +2636,48 @@ static void bc_dispatch(struct port *p, enum 
> fsm_event event, int mdiff)
>       }
>  }
>  
> +void port_change_phc(struct port *p)
> +{
> +     int required_modes;
> +
> +     /* Only switch phc with HW time stamping mode */
> +     if (!interface_tsinfo_valid(p->iface) ||
> +         interface_phc_index(p->iface) < 0)
> +             return;
> +
> +     required_modes = clock_required_modes(p->clock);
> +     if (!interface_tsmodes_supported(p->iface, required_modes)) {
> +             pr_err("interface '%s' does not support requested "
> +                    "timestamping mode, set link status down by force.",
> +                    interface_label(p->iface));
> +             p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
> +     } else if (p->phc_from_cmdline) {
> +             pr_warning("%s: taking /dev/ptp%d from the "
> +                        "command line, not the attached ptp%d",
> +                        p->log_name, p->phc_index,
> +                        interface_phc_index(p->iface));
> +     } else if (p->phc_index != interface_phc_index(p->iface)) {
> +             p->phc_index = interface_phc_index(p->iface);
> +
> +             if (clock_switch_phc(p->clock, p->phc_index)) {
> +                     p->last_fault_type = FT_SWITCH_PHC;
> +                     port_dispatch(p, EV_FAULT_DETECTED, 0);
> +                     return;
> +             }
> +             clock_sync_interval(p->clock, p->log_sync_interval);
> +
> +             /* Ensure TS_LABEL_CHANGED is set for failover when
> +              * PHC changed as we may not call port_change_phc()
> +              * from port_link_status().
> +              */
> +             p->link_status |= TS_LABEL_CHANGED;
> +     }
> +}
> +
>  void port_link_status(void *ctx, int linkup, int ts_index)
>  {
>       char ts_label[MAX_IFNAME_SIZE + 1] = {0};
> -     int link_state, required_modes;
> +     int link_state;
>       const char *old_ts_label;
>       struct port *p = ctx;
>  
> @@ -2663,32 +2701,7 @@ void port_link_status(void *ctx, int linkup, int 
> ts_index)
>       if (p->link_status & LINK_UP &&
>           (p->link_status & LINK_STATE_CHANGED || p->link_status & 
> TS_LABEL_CHANGED)) {
>               interface_get_tsinfo(p->iface);
> -
> -             /* Only switch phc with HW time stamping mode */
> -             if (interface_tsinfo_valid(p->iface) &&
> -                 interface_phc_index(p->iface) >= 0) {
> -                     required_modes = clock_required_modes(p->clock);
> -                     if (!interface_tsmodes_supported(p->iface, 
> required_modes)) {
> -                             pr_err("interface '%s' does not support 
> requested "
> -                                    "timestamping mode, set link status down 
> by force.",
> -                                    interface_label(p->iface));
> -                             p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
> -                     } else if (p->phc_from_cmdline) {
> -                             pr_warning("%s: taking /dev/ptp%d from the "
> -                                        "command line, not the attached 
> ptp%d",
> -                                        p->log_name, p->phc_index,
> -                                        interface_phc_index(p->iface));
> -                     } else if (p->phc_index != 
> interface_phc_index(p->iface)) {
> -                             p->phc_index = interface_phc_index(p->iface);
> -
> -                             if (clock_switch_phc(p->clock, p->phc_index)) {
> -                                     p->last_fault_type = FT_SWITCH_PHC;
> -                                     port_dispatch(p, EV_FAULT_DETECTED, 0);
> -                                     return;
> -                             }
> -                             clock_sync_interval(p->clock, 
> p->log_sync_interval);
> -                     }
> -             }
> +             port_change_phc(p);
>       }

... alreadly improves the readability of the code.  Please put that
bit into its own patch.

> @@ -2802,7 +2815,12 @@ static enum fsm_event bc_event(struct port *p, int 
> fd_index)
>  
>       case FD_RTNL:
>               pr_debug("%s: received link status notification", p->log_name);
> -             rtnl_link_status(fd, p->name, port_link_status, p);
> +             if (!interface_get_tsinfo(p->iface) &&
> +                 (p->phc_index != interface_phc_index(p->iface)))
> +                     port_change_phc(p);
> +             else
> +                     rtnl_link_status(fd, p->name, port_link_status, p);

However this part will cause issues.  When the RTNL event occurs,
there can be multiple messages.  The callback is invoked on each one:

        rtnl_link_status()
        {
                ...
                for ( ; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
                        ...
                        if (cb)
                                cb(ctx, link_up, slave_index);
                }
        }

You new logic will drop link up/down notifications (or anything else
we might add later).

In some cases, your change will only call port_change_phc() but will
avoid the important other part of port_link_status():

        /*
         * A port going down can affect the BMCA result.
         * Force a state decision event.
         */
        if (p->link_status & LINK_DOWN)
                clock_set_sde(p->clock, 1);

Why not simply remove the extra test and check
 (p->phc_index != interface_phc_index(p->iface))
in the port_change_phc() helper function?

What am I missing?

Thanks,
Richard





_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to