Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f92bed3 authored by Upinder Malhi's avatar Upinder Malhi Committed by Roland Dreier
Browse files

IB/usnic: Add UDP support to usnic_fwd.[hc]



Add *ip field* to *struct usnic_fwd_dev* as well as new *functions* to
manipulate the *ip field.*  Furthermore, add new functions for
programming UDP flows in the forwarding device.

Signed-off-by: default avatarUpinder Malhi <umalhi@cisco.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent b85caf47
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -95,6 +95,29 @@ void usnic_fwd_set_mac(struct usnic_fwd_dev *ufdev, char mac[ETH_ALEN])
	spin_unlock(&ufdev->lock);
}

int usnic_fwd_add_ipaddr(struct usnic_fwd_dev *ufdev, __be32 inaddr)
{
	int status;

	spin_lock(&ufdev->lock);
	if (ufdev->inaddr == 0) {
		ufdev->inaddr = inaddr;
		status = 0;
	} else {
		status = -EFAULT;
	}
	spin_unlock(&ufdev->lock);

	return status;
}

void usnic_fwd_del_ipaddr(struct usnic_fwd_dev *ufdev)
{
	spin_lock(&ufdev->lock);
	ufdev->inaddr = 0;
	spin_unlock(&ufdev->lock);
}

void usnic_fwd_carrier_up(struct usnic_fwd_dev *ufdev)
{
	spin_lock(&ufdev->lock);
@@ -126,6 +149,30 @@ static int usnic_fwd_dev_ready_locked(struct usnic_fwd_dev *ufdev)
	return 0;
}

static int validate_filter_locked(struct usnic_fwd_dev *ufdev,
					struct filter *filter)
{

	lockdep_assert_held(&ufdev->lock);

	if (filter->type == FILTER_IPV4_5TUPLE) {
		if (!(filter->u.ipv4.flags & FILTER_FIELD_5TUP_DST_AD))
			return -EACCES;
		if (!(filter->u.ipv4.flags & FILTER_FIELD_5TUP_DST_PT))
			return -EBUSY;
		else if (ufdev->inaddr == 0)
			return -EINVAL;
		else if (filter->u.ipv4.dst_port == 0)
			return -ERANGE;
		else if (ntohl(ufdev->inaddr) != filter->u.ipv4.dst_addr)
			return -EFAULT;
		else
			return 0;
	}

	return 0;
}

static void fill_tlv(struct filter_tlv *tlv, struct filter *filter,
		struct filter_action *action)
{
@@ -177,6 +224,13 @@ usnic_fwd_alloc_flow(struct usnic_fwd_dev *ufdev, struct filter *filter,
		goto out_free_tlv;
	}

	status = validate_filter_locked(ufdev, filter);
	if (status) {
		usnic_err("Failed to validate filter with status %d\n",
				status);
		goto out_free_tlv;
	}

	/* Issue Devcmd */
	a0 = tlv_pa;
	a1 = tlv_size;
+21 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ struct usnic_fwd_dev {
	bool				link_up;
	char				mac[ETH_ALEN];
	unsigned int			mtu;
	__be32				inaddr;
	char				name[IFNAMSIZ+1];
};

@@ -58,6 +59,8 @@ struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev);
void usnic_fwd_dev_free(struct usnic_fwd_dev *ufdev);

void usnic_fwd_set_mac(struct usnic_fwd_dev *ufdev, char mac[ETH_ALEN]);
int usnic_fwd_add_ipaddr(struct usnic_fwd_dev *ufdev, __be32 inaddr);
void usnic_fwd_del_ipaddr(struct usnic_fwd_dev *ufdev);
void usnic_fwd_carrier_up(struct usnic_fwd_dev *ufdev);
void usnic_fwd_carrier_down(struct usnic_fwd_dev *ufdev);
void usnic_fwd_set_mtu(struct usnic_fwd_dev *ufdev, unsigned int mtu);
@@ -89,4 +92,22 @@ static inline void usnic_fwd_init_usnic_filter(struct filter *filter,
	filter->u.usnic.usnic_id = usnic_id;
}

static inline void usnic_fwd_init_udp_filter(struct filter *filter,
						uint32_t daddr, uint16_t dport)
{
	filter->type = FILTER_IPV4_5TUPLE;
	filter->u.ipv4.flags = FILTER_FIELD_5TUP_PROTO;
	filter->u.ipv4.protocol = PROTO_UDP;

	if (daddr) {
		filter->u.ipv4.flags |= FILTER_FIELD_5TUP_DST_AD;
		filter->u.ipv4.dst_addr = daddr;
	}

	if (dport) {
		filter->u.ipv4.flags |= FILTER_FIELD_5TUP_DST_PT;
		filter->u.ipv4.dst_port = dport;
	}
}

#endif /* !USNIC_FWD_H_ */