Commit 75687cd0 authored by Íñigo Huguet's avatar Íñigo Huguet Committed by Jakub Kicinski
Browse files

sfc: allow insertion of filters for unicast PTP



Add a second list for unicast filters and generalize the
efx_ptp_insert/remove_filters functions to allow acting in any of the 2
lists.

No filters for unicast are inserted yet. That will be done in the next
patch.

The reason to use 2 different lists instead of a single one is that, in
next patches, we will want to check if unicast filters are already added
and if they're expired. We don't need that for multicast filters.

Reported-by: default avatarYalin Li <yalli@redhat.com>
Signed-off-by: default avatarÍñigo Huguet <ihuguet@redhat.com>
Reviewed-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent e790fc15
Loading
Loading
Loading
Loading
+36 −23
Original line number Diff line number Diff line
@@ -239,6 +239,7 @@ struct efx_ptp_rxfilter {
 * @reset_required: A serious error has occurred and the PTP task needs to be
 *                  reset (disable, enable).
 * @rxfilters_mcast: Receive filters for multicast PTP packets
 * @rxfilters_ucast: Receive filters for unicast PTP packets
 * @config: Current timestamp configuration
 * @enabled: PTP operation enabled
 * @mode: Mode in which PTP operating (PTP version)
@@ -308,6 +309,7 @@ struct efx_ptp_data {
	struct work_struct work;
	bool reset_required;
	struct list_head rxfilters_mcast;
	struct list_head rxfilters_ucast;
	struct hwtstamp_config config;
	bool enabled;
	unsigned int mode;
@@ -1296,12 +1298,12 @@ static inline void efx_ptp_process_rx(struct efx_nic *efx, struct sk_buff *skb)
	local_bh_enable();
}

static void efx_ptp_remove_multicast_filters(struct efx_nic *efx)
static void efx_ptp_remove_filters(struct efx_nic *efx,
				   struct list_head *filter_list)
{
	struct efx_ptp_data *ptp = efx->ptp_data;
	struct efx_ptp_rxfilter *rxfilter, *tmp;

	list_for_each_entry_safe(rxfilter, tmp, &ptp->rxfilters_mcast, list) {
	list_for_each_entry_safe(rxfilter, tmp, filter_list, list) {
		efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
					  rxfilter->handle);
		list_del(&rxfilter->list);
@@ -1320,9 +1322,9 @@ static void efx_ptp_init_filter(struct efx_nic *efx,
}

static int efx_ptp_insert_filter(struct efx_nic *efx,
				 struct list_head *filter_list,
				 struct efx_filter_spec *spec)
{
	struct efx_ptp_data *ptp = efx->ptp_data;
	struct efx_ptp_rxfilter *rxfilter;
	int rc;

@@ -1335,7 +1337,7 @@ static int efx_ptp_insert_filter(struct efx_nic *efx,
		goto fail;

	rxfilter->handle = rc;
	list_add(&rxfilter->list, &ptp->rxfilters_mcast);
	list_add(&rxfilter->list, filter_list);

	return 0;

@@ -1344,28 +1346,31 @@ static int efx_ptp_insert_filter(struct efx_nic *efx,
	return rc;
}

static int efx_ptp_insert_ipv4_filter(struct efx_nic *efx, u16 port)
static int efx_ptp_insert_ipv4_filter(struct efx_nic *efx,
				      struct list_head *filter_list,
				      __be32 addr, u16 port)
{
	struct efx_filter_spec spec;

	efx_ptp_init_filter(efx, &spec);
	efx_filter_set_ipv4_local(&spec, IPPROTO_UDP, htonl(PTP_ADDR_IPV4),
				  htons(port));
	return efx_ptp_insert_filter(efx, &spec);
	efx_filter_set_ipv4_local(&spec, IPPROTO_UDP, addr, htons(port));
	return efx_ptp_insert_filter(efx, filter_list, &spec);
}

static int efx_ptp_insert_ipv6_filter(struct efx_nic *efx, u16 port)
static int efx_ptp_insert_ipv6_filter(struct efx_nic *efx,
				      struct list_head *filter_list,
				      struct in6_addr *addr, u16 port)
{
	const struct in6_addr addr = {{PTP_ADDR_IPV6}};
	struct efx_filter_spec spec;

	efx_ptp_init_filter(efx, &spec);
	efx_filter_set_ipv6_local(&spec, IPPROTO_UDP, &addr, htons(port));
	return efx_ptp_insert_filter(efx, &spec);
	efx_filter_set_ipv6_local(&spec, IPPROTO_UDP, addr, htons(port));
	return efx_ptp_insert_filter(efx, filter_list, &spec);
}

static int efx_ptp_insert_eth_filter(struct efx_nic *efx)
static int efx_ptp_insert_eth_multicast_filter(struct efx_nic *efx)
{
	struct efx_ptp_data *ptp = efx->ptp_data;
	const u8 addr[ETH_ALEN] = PTP_ADDR_ETHER;
	struct efx_filter_spec spec;

@@ -1373,7 +1378,7 @@ static int efx_ptp_insert_eth_filter(struct efx_nic *efx)
	efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC, addr);
	spec.match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
	spec.ether_type = htons(ETH_P_1588);
	return efx_ptp_insert_filter(efx, &spec);
	return efx_ptp_insert_filter(efx, &ptp->rxfilters_mcast, &spec);
}

static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
@@ -1387,11 +1392,13 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
	/* Must filter on both event and general ports to ensure
	 * that there is no packet re-ordering.
	 */
	rc = efx_ptp_insert_ipv4_filter(efx, PTP_EVENT_PORT);
	rc = efx_ptp_insert_ipv4_filter(efx, &ptp->rxfilters_mcast,
					htonl(PTP_ADDR_IPV4), PTP_EVENT_PORT);
	if (rc < 0)
		goto fail;

	rc = efx_ptp_insert_ipv4_filter(efx, PTP_GENERAL_PORT);
	rc = efx_ptp_insert_ipv4_filter(efx, &ptp->rxfilters_mcast,
					htonl(PTP_ADDR_IPV4), PTP_GENERAL_PORT);
	if (rc < 0)
		goto fail;

@@ -1399,15 +1406,19 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
	 * PTP over IPv6 and Ethernet
	 */
	if (efx_ptp_use_mac_tx_timestamps(efx)) {
		rc = efx_ptp_insert_ipv6_filter(efx, PTP_EVENT_PORT);
		struct in6_addr ipv6_addr = {{PTP_ADDR_IPV6}};

		rc = efx_ptp_insert_ipv6_filter(efx, &ptp->rxfilters_mcast,
						&ipv6_addr, PTP_EVENT_PORT);
		if (rc < 0)
			goto fail;

		rc = efx_ptp_insert_ipv6_filter(efx, PTP_GENERAL_PORT);
		rc = efx_ptp_insert_ipv6_filter(efx, &ptp->rxfilters_mcast,
						&ipv6_addr, PTP_GENERAL_PORT);
		if (rc < 0)
			goto fail;

		rc = efx_ptp_insert_eth_filter(efx);
		rc = efx_ptp_insert_eth_multicast_filter(efx);
		if (rc < 0)
			goto fail;
	}
@@ -1415,7 +1426,7 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
	return 0;

fail:
	efx_ptp_remove_multicast_filters(efx);
	efx_ptp_remove_filters(efx, &ptp->rxfilters_mcast);
	return rc;
}

@@ -1440,7 +1451,7 @@ static int efx_ptp_start(struct efx_nic *efx)
	return 0;

fail:
	efx_ptp_remove_multicast_filters(efx);
	efx_ptp_remove_filters(efx, &ptp->rxfilters_mcast);
	return rc;
}

@@ -1456,7 +1467,8 @@ static int efx_ptp_stop(struct efx_nic *efx)

	rc = efx_ptp_disable(efx);

	efx_ptp_remove_multicast_filters(efx);
	efx_ptp_remove_filters(efx, &ptp->rxfilters_mcast);
	efx_ptp_remove_filters(efx, &ptp->rxfilters_ucast);

	/* Make sure RX packets are really delivered */
	efx_ptp_deliver_rx_queue(&efx->ptp_data->rxq);
@@ -1588,6 +1600,7 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
		list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list);

	INIT_LIST_HEAD(&ptp->rxfilters_mcast);
	INIT_LIST_HEAD(&ptp->rxfilters_ucast);

	/* Get the NIC PTP attributes and set up time conversions */
	rc = efx_ptp_get_attributes(efx);