On Thu, Apr 25, 2019 at 09:40:06PM +0800, Hangbin Liu wrote: > On Tue, Apr 23, 2019 at 11:32:13AM +0200, Miroslav Lichvar wrote: > > If those values I described above were in an array called ts_map > > indexed by the RX filter enum, I think the check could just be: > > > > (ts_map[old_filter] & ts_map[new_filter]) == tsmap[old_filter] > > > > The individual bits would correspond to: > > > > PTP_V1_L4_SYNC > > PTP_V1_L4_DELAY_REQ > > PTP_V2_L4_SYNC > > PTP_V2_L4_DELAY_REQ > > PTP_V2_L2_SYNC > > PTP_V2_L2_DELAY_REQ > > NTP_ALL > > > > And the remaining RX filters would be combinations of those. > > > > -- > Hi Miroslav, Richard, > > Here is a draft patch with your idea. I haven't test it and it may has some > issues. But the logic should looks like what you said. The copy_from/to_user > is a little ugly, but I haven't come up with a more gentle way. > > Would you please help have a look at it and see which way we should use? > Drop SIOCSHWTSTAMP in container or add a filter on macvlan(maybe only in > container)?
Hi Richard, Any suggestion? Thanks Hangbin > > diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c > index 4a6be8fab884..0f87a42fc61c 100644 > --- a/drivers/net/macvlan.c > +++ b/drivers/net/macvlan.c > @@ -824,18 +824,75 @@ static int macvlan_change_mtu(struct net_device *dev, > int new_mtu) > return 0; > } > > +int check_rx_filter(unsigned int new_filter, unsigned int old_filter) > +{ > + u8 ts_map[HWTSTAMP_FILTER_NTP_ALL]; > + > + memset(ts_map, 0, sizeof(ts_map)); > + > + ts_map[HWTSTAMP_FILTER_PTP_V1_L4_SYNC - 1] = 0x01; > + ts_map[HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ - 1] = 0x02; > + ts_map[HWTSTAMP_FILTER_PTP_V1_L4_EVENT - 1] = 0x03; > + > + ts_map[HWTSTAMP_FILTER_PTP_V2_L4_SYNC - 1] = 0x11; > + ts_map[HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ - 1] = 0x12; > + ts_map[HWTSTAMP_FILTER_PTP_V2_L4_EVENT - 1] = 0x13; > + > + ts_map[HWTSTAMP_FILTER_PTP_V2_SYNC - 1] = 0x31; > + ts_map[HWTSTAMP_FILTER_PTP_V2_DELAY_REQ - 1] = 0x32; > + ts_map[HWTSTAMP_FILTER_PTP_V2_EVENT - 1] = 0x33; > + > + ts_map[HWTSTAMP_FILTER_NTP_ALL - 1] = 0xF0; > + ts_map[HWTSTAMP_FILTER_ALL - 1] = 0xFF; > + > + if ((ts_map[new_filter] & ts_map[old_filter]) == ts_map[old_filter]) > + return 0; > + else > + return -EACCES; > +} > + > static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int > cmd) > { > struct net_device *real_dev = macvlan_dev_real_dev(dev); > const struct net_device_ops *ops = real_dev->netdev_ops; > - struct ifreq ifrr; > + unsigned int old_filter, new_filter, new_tx_type; > + struct hwtstamp_config new_stmpconf, old_stmpconf; > int err = -EOPNOTSUPP; > + struct ifreq ifrr; > + > + /* Get new rx_filter */ > + if (copy_from_user(&new_stmpconf, ifr->ifr_data, sizeof(new_stmpconf))) > { > + return -EFAULT; > + } else { > + new_tx_type = new_stmpconf.tx_type; > + new_filter = new_stmpconf.rx_filter; > + } > > + /* Get old rx_filter */ > strncpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ); > ifrr.ifr_ifru = ifr->ifr_ifru; > > + if (netif_device_present(real_dev) && ops->ndo_do_ioctl) > + err = ops->ndo_do_ioctl(real_dev, &ifrr, SIOCGHWTSTAMP); > + > + if (!err && copy_from_user(&old_stmpconf, ifrr.ifr_data, > sizeof(old_stmpconf))) > + old_filter = old_stmpconf.rx_filter; > + else > + return err; > + > + /* Copy new data back */ > + if (copy_to_user(ifrr.ifr_data, &new_stmpconf, sizeof(new_stmpconf))) > + return -EFAULT; > + > switch (cmd) { > case SIOCSHWTSTAMP: > + if (new_tx_type != HWTSTAMP_TX_ON || > + new_filter == HWTSTAMP_FILTER_SOME) > + return err; > + > + err = check_rx_filter(new_filter, old_filter); > + if (err) > + break; > case SIOCGHWTSTAMP: > if (netif_device_present(real_dev) && ops->ndo_do_ioctl) > err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd); > -- > 2.19.2 >