src/dpdk/drivers/net/ixgbe/ixgbe_fdir.c
static int
fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
			union ixgbe_atr_input *input, uint8_t queue,
			uint32_t fdircmd, uint32_t fdirhash,
			enum rte_fdir_mode mode)
{
	uint32_t fdirport, fdirvlan;
	u32 addr_low, addr_high;
	u32 tunnel_type = 0;
	int err = 0;
	volatile uint32_t *reg;

	if (mode == RTE_FDIR_MODE_PERFECT) {
		/* record the IPv4 address (big-endian)
		 * can not use IXGBE_WRITE_REG.
		 */
		reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRIPSA);
		*reg = input->formatted.src_ip[0];
		reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRIPDA);
		*reg = input->formatted.dst_ip[0];

		/* record source and destination port (little-endian)*/
		fdirport = IXGBE_NTOHS(input->formatted.dst_port);
		fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
		fdirport |= IXGBE_NTOHS(input->formatted.src_port);
		IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
	} else if (mode >= RTE_FDIR_MODE_PERFECT_MAC_VLAN &&
		   mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) {
		/* for mac vlan and tunnel modes */
		addr_low = ((u32)input->formatted.inner_mac[0] |
			    ((u32)input->formatted.inner_mac[1] << 8) |
			    ((u32)input->formatted.inner_mac[2] << 16) |
			    ((u32)input->formatted.inner_mac[3] << 24));
		addr_high = ((u32)input->formatted.inner_mac[4] |
			     ((u32)input->formatted.inner_mac[5] << 8));

		if (mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), addr_low);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), addr_high);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), 0);
		} else {
			/* tunnel mode */
			if (input->formatted.tunnel_type)
				tunnel_type = 0x80000000;
			tunnel_type |= addr_high;
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), addr_low);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), tunnel_type);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2),
					input->formatted.tni_vni);
		}
		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, 0);
		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, 0);
		IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, 0);
	}

	/* record vlan (little-endian) and flex_bytes(big-endian) */
	fdirvlan = input->formatted.flex_bytes;
	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
	fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id);
	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);

	/* configure FDIRHASH register */
	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);

	/*
	 * flush all previous writes to make certain registers are
	 * programmed prior to issuing the command
	 */
	IXGBE_WRITE_FLUSH(hw);

	/* configure FDIRCMD register */
	fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW |
		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
	fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
	fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
	fdircmd |= (uint32_t)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;

	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);

	PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash);

	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
	if (err < 0)
		PMD_DRV_LOG(ERR, "Timeout writing flow director filter.");

	return err;
}
/*
 * This is based on ixgbe_fdir_write_perfect_filter_82599() in
 * base/ixgbe_82599.c, with the ability to set extra flags in FDIRCMD register
 * added, and IPv6 support also added. The hash value is also pre-calculated
 * as the pballoc value is needed to do it.
 */
This is based on ixgbe_fdir_write_perfect_filter_82599() in
base/ixgbe_82599.c, with the ability to set extra flags in FDIRCMD register
added, and IPv6 support also added. The hash value is also pre-calculated
as the pballoc value is needed to do it.
This is based on ixgbe_fdir_write_perfect_filter_82599 () in base / ixgbe_82599 . c with the ability to set extra flags in FDIRCMD register added and IPv6 support also added . The hash value is also pre - calculated as the pballoc value is needed to do it .
static int
fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
			union ixgbe_atr_input *input, uint8_t queue,
			uint32_t fdircmd, uint32_t fdirhash,
			enum rte_fdir_mode mode)
{
	uint32_t fdirport, fdirvlan;
	u32 addr_low, addr_high;
	u32 tunnel_type = 0;
	int err = 0;
	volatile uint32_t *reg;
	if (mode == RTE_FDIR_MODE_PERFECT) {
		reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRIPSA);
		*reg = input->formatted.src_ip[0];
		reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRIPDA);
		*reg = input->formatted.dst_ip[0];
		fdirport = IXGBE_NTOHS(input->formatted.dst_port);
		fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
		fdirport |= IXGBE_NTOHS(input->formatted.src_port);
		IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
	} else if (mode >= RTE_FDIR_MODE_PERFECT_MAC_VLAN &&
		   mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) {
		addr_low = ((u32)input->formatted.inner_mac[0] |
			    ((u32)input->formatted.inner_mac[1] << 8) |
			    ((u32)input->formatted.inner_mac[2] << 16) |
			    ((u32)input->formatted.inner_mac[3] << 24));
		addr_high = ((u32)input->formatted.inner_mac[4] |
			     ((u32)input->formatted.inner_mac[5] << 8));
		if (mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), addr_low);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), addr_high);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), 0);
		} else {
			if (input->formatted.tunnel_type)
				tunnel_type = 0x80000000;
			tunnel_type |= addr_high;
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), addr_low);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), tunnel_type);
			IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2),
					input->formatted.tni_vni);
		}
		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, 0);
		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, 0);
		IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, 0);
	}
	fdirvlan = input->formatted.flex_bytes;
	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
	fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id);
	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
	IXGBE_WRITE_FLUSH(hw);
	fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW |
		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
	fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
	fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
	fdircmd |= (uint32_t)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
	PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash);
	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
	if (err < 0)
		PMD_DRV_LOG(ERR, "Timeout writing flow director filter.");
	return err;
}
static int fdir_write_perfect_filter_82599 ( struct ixgbe_hw * hw , union ixgbe_atr_input * input , uint8_t queue , uint32_t fdircmd , uint32_t fdirhash , enum rte_fdir_mode mode ) { uint32_t fdirport , fdirvlan ; u32 addr_low , addr_high ; u32 tunnel_type = 0 ; int err = 0 ; volatile uint32_t * reg ; if ( mode == RTE_FDIR_MODE_PERFECT ) { reg = IXGBE_PCI_REG_ADDR ( hw , IXGBE_FDIRIPSA ) ; * reg = input -> formatted . src_ip [ 0 ] ; reg = IXGBE_PCI_REG_ADDR ( hw , IXGBE_FDIRIPDA ) ; * reg = input -> formatted . dst_ip [ 0 ] ; fdirport = IXGBE_NTOHS ( input -> formatted . dst_port ) ; fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT ; fdirport |= IXGBE_NTOHS ( input -> formatted . src_port ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRPORT , fdirport ) ; } else if ( mode >= RTE_FDIR_MODE_PERFECT_MAC_VLAN && mode <= RTE_FDIR_MODE_PERFECT_TUNNEL ) { addr_low = ( ( u32 ) input -> formatted . inner_mac [ 0 ] | ( ( u32 ) input -> formatted . inner_mac [ 1 ] << 8 ) | ( ( u32 ) input -> formatted . inner_mac [ 2 ] << 16 ) | ( ( u32 ) input -> formatted . inner_mac [ 3 ] << 24 ) ) ; addr_high = ( ( u32 ) input -> formatted . inner_mac [ 4 ] | ( ( u32 ) input -> formatted . inner_mac [ 5 ] << 8 ) ) ; if ( mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN ) { IXGBE_WRITE_REG ( hw , IXGBE_FDIRSIPv6 ( 0 ) , addr_low ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRSIPv6 ( 1 ) , addr_high ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRSIPv6 ( 2 ) , 0 ) ; } else { if ( input -> formatted . tunnel_type ) tunnel_type = 0x80000000 ; tunnel_type |= addr_high ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRSIPv6 ( 0 ) , addr_low ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRSIPv6 ( 1 ) , tunnel_type ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRSIPv6 ( 2 ) , input -> formatted . tni_vni ) ; } IXGBE_WRITE_REG ( hw , IXGBE_FDIRIPSA , 0 ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRIPDA , 0 ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRPORT , 0 ) ; } fdirvlan = input -> formatted . flex_bytes ; fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT ; fdirvlan |= IXGBE_NTOHS ( input -> formatted . vlan_id ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRVLAN , fdirvlan ) ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRHASH , fdirhash ) ; IXGBE_WRITE_FLUSH ( hw ) ; fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN ; fdircmd |= input -> formatted . flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT ; fdircmd |= ( uint32_t ) queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT ; fdircmd |= ( uint32_t ) input -> formatted . vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT ; IXGBE_WRITE_REG ( hw , IXGBE_FDIRCMD , fdircmd ) ; PMD_DRV_LOG ( DEBUG , " " , queue , fdirhash ) ; err = ixgbe_fdir_check_cmd_complete ( hw , & fdircmd ) ; if ( err < 0 ) PMD_DRV_LOG ( ERR , " " ) ; return err ; }
This is based on ixgbe_fdir_write_perfect_filter_82599() in
 base/ixgbe_82599.c, with the ability to set extra flags in FDIRCMD register
 added, and IPv6 support also added.
This is based on ixgbe_fdir_write_perfect_filter_82599 () in base / ixgbe_82599 . c with the ability to set extra flags in FDIRCMD register added and IPv6 support also added .
/* record the IPv4 address (big-endian)
		 * can not use IXGBE_WRITE_REG.
		 */ /* record source and destination port (little-endian)*/ /* for mac vlan and tunnel modes */ /* tunnel mode */ /* record vlan (little-endian) and flex_bytes(big-endian) */ /* configure FDIRHASH register */ /*
	 * flush all previous writes to make certain registers are
	 * programmed prior to issuing the command
	 */ /* configure FDIRCMD register */