brintos

brintos / linux-shallow public Read only

0
0
Text · 8.8 KiB · 6466311 Raw
337 lines · c
1/*2 * This file is part of the Chelsio T4 Ethernet driver for Linux.3 *4 * Copyright (c) 2016 Chelsio Communications, Inc. All rights reserved.5 *6 * This software is available to you under a choice of one of two7 * licenses.  You may choose to be licensed under the terms of the GNU8 * General Public License (GPL) Version 2, available from the file9 * COPYING in the main directory of this source tree, or the10 * OpenIB.org BSD license below:11 *12 *     Redistribution and use in source and binary forms, with or13 *     without modification, are permitted provided that the following14 *     conditions are met:15 *16 *      - Redistributions of source code must retain the above17 *        copyright notice, this list of conditions and the following18 *        disclaimer.19 *20 *      - Redistributions in binary form must reproduce the above21 *        copyright notice, this list of conditions and the following22 *        disclaimer in the documentation and/or other materials23 *        provided with the distribution.24 *25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE32 * SOFTWARE.33 */34 35#ifndef __CXGB4_TC_U32_PARSE_H36#define __CXGB4_TC_U32_PARSE_H37 38struct cxgb4_match_field {39	int off; /* Offset from the beginning of the header to match */40	/* Fill the value/mask pair in the spec if matched */41	int (*val)(struct ch_filter_specification *f, __be32 val, __be32 mask);42};43 44/* IPv4 match fields */45static inline int cxgb4_fill_ipv4_tos(struct ch_filter_specification *f,46				      __be32 val, __be32 mask)47{48	f->val.tos  = (ntohl(val)  >> 16) & 0x000000FF;49	f->mask.tos = (ntohl(mask) >> 16) & 0x000000FF;50 51	return 0;52}53 54static inline int cxgb4_fill_ipv4_frag(struct ch_filter_specification *f,55				       __be32 val, __be32 mask)56{57	u32 mask_val;58	u8 frag_val;59 60	frag_val = (ntohl(val) >> 13) & 0x00000007;61	mask_val = ntohl(mask) & 0x0000FFFF;62 63	if (frag_val == 0x1 && mask_val != 0x3FFF) { /* MF set */64		f->val.frag = 1;65		f->mask.frag = 1;66	} else if (frag_val == 0x2 && mask_val != 0x3FFF) { /* DF set */67		f->val.frag = 0;68		f->mask.frag = 1;69	} else {70		return -EINVAL;71	}72 73	return 0;74}75 76static inline int cxgb4_fill_ipv4_proto(struct ch_filter_specification *f,77					__be32 val, __be32 mask)78{79	f->val.proto  = (ntohl(val)  >> 16) & 0x000000FF;80	f->mask.proto = (ntohl(mask) >> 16) & 0x000000FF;81 82	return 0;83}84 85static inline int cxgb4_fill_ipv4_src_ip(struct ch_filter_specification *f,86					 __be32 val, __be32 mask)87{88	memcpy(&f->val.fip[0],  &val,  sizeof(u32));89	memcpy(&f->mask.fip[0], &mask, sizeof(u32));90 91	return 0;92}93 94static inline int cxgb4_fill_ipv4_dst_ip(struct ch_filter_specification *f,95					 __be32 val, __be32 mask)96{97	memcpy(&f->val.lip[0],  &val,  sizeof(u32));98	memcpy(&f->mask.lip[0], &mask, sizeof(u32));99 100	return 0;101}102 103static const struct cxgb4_match_field cxgb4_ipv4_fields[] = {104	{ .off = 0,  .val = cxgb4_fill_ipv4_tos },105	{ .off = 4,  .val = cxgb4_fill_ipv4_frag },106	{ .off = 8,  .val = cxgb4_fill_ipv4_proto },107	{ .off = 12, .val = cxgb4_fill_ipv4_src_ip },108	{ .off = 16, .val = cxgb4_fill_ipv4_dst_ip },109	{ .val = NULL }110};111 112/* IPv6 match fields */113static inline int cxgb4_fill_ipv6_tos(struct ch_filter_specification *f,114				      __be32 val, __be32 mask)115{116	f->val.tos  = (ntohl(val)  >> 20) & 0x000000FF;117	f->mask.tos = (ntohl(mask) >> 20) & 0x000000FF;118 119	return 0;120}121 122static inline int cxgb4_fill_ipv6_proto(struct ch_filter_specification *f,123					__be32 val, __be32 mask)124{125	f->val.proto  = (ntohl(val)  >> 8) & 0x000000FF;126	f->mask.proto = (ntohl(mask) >> 8) & 0x000000FF;127 128	return 0;129}130 131static inline int cxgb4_fill_ipv6_src_ip0(struct ch_filter_specification *f,132					  __be32 val, __be32 mask)133{134	memcpy(&f->val.fip[0],  &val,  sizeof(u32));135	memcpy(&f->mask.fip[0], &mask, sizeof(u32));136 137	return 0;138}139 140static inline int cxgb4_fill_ipv6_src_ip1(struct ch_filter_specification *f,141					  __be32 val, __be32 mask)142{143	memcpy(&f->val.fip[4],  &val,  sizeof(u32));144	memcpy(&f->mask.fip[4], &mask, sizeof(u32));145 146	return 0;147}148 149static inline int cxgb4_fill_ipv6_src_ip2(struct ch_filter_specification *f,150					  __be32 val, __be32 mask)151{152	memcpy(&f->val.fip[8],  &val,  sizeof(u32));153	memcpy(&f->mask.fip[8], &mask, sizeof(u32));154 155	return 0;156}157 158static inline int cxgb4_fill_ipv6_src_ip3(struct ch_filter_specification *f,159					  __be32 val, __be32 mask)160{161	memcpy(&f->val.fip[12],  &val,  sizeof(u32));162	memcpy(&f->mask.fip[12], &mask, sizeof(u32));163 164	return 0;165}166 167static inline int cxgb4_fill_ipv6_dst_ip0(struct ch_filter_specification *f,168					  __be32 val, __be32 mask)169{170	memcpy(&f->val.lip[0],  &val,  sizeof(u32));171	memcpy(&f->mask.lip[0], &mask, sizeof(u32));172 173	return 0;174}175 176static inline int cxgb4_fill_ipv6_dst_ip1(struct ch_filter_specification *f,177					  __be32 val, __be32 mask)178{179	memcpy(&f->val.lip[4],  &val,  sizeof(u32));180	memcpy(&f->mask.lip[4], &mask, sizeof(u32));181 182	return 0;183}184 185static inline int cxgb4_fill_ipv6_dst_ip2(struct ch_filter_specification *f,186					  __be32 val, __be32 mask)187{188	memcpy(&f->val.lip[8],  &val,  sizeof(u32));189	memcpy(&f->mask.lip[8], &mask, sizeof(u32));190 191	return 0;192}193 194static inline int cxgb4_fill_ipv6_dst_ip3(struct ch_filter_specification *f,195					  __be32 val, __be32 mask)196{197	memcpy(&f->val.lip[12],  &val,  sizeof(u32));198	memcpy(&f->mask.lip[12], &mask, sizeof(u32));199 200	return 0;201}202 203static const struct cxgb4_match_field cxgb4_ipv6_fields[] = {204	{ .off = 0,  .val = cxgb4_fill_ipv6_tos },205	{ .off = 4,  .val = cxgb4_fill_ipv6_proto },206	{ .off = 8,  .val = cxgb4_fill_ipv6_src_ip0 },207	{ .off = 12, .val = cxgb4_fill_ipv6_src_ip1 },208	{ .off = 16, .val = cxgb4_fill_ipv6_src_ip2 },209	{ .off = 20, .val = cxgb4_fill_ipv6_src_ip3 },210	{ .off = 24, .val = cxgb4_fill_ipv6_dst_ip0 },211	{ .off = 28, .val = cxgb4_fill_ipv6_dst_ip1 },212	{ .off = 32, .val = cxgb4_fill_ipv6_dst_ip2 },213	{ .off = 36, .val = cxgb4_fill_ipv6_dst_ip3 },214	{ .val = NULL }215};216 217/* TCP/UDP match */218static inline int cxgb4_fill_l4_ports(struct ch_filter_specification *f,219				      __be32 val, __be32 mask)220{221	f->val.fport  = ntohl(val)  >> 16;222	f->mask.fport = ntohl(mask) >> 16;223	f->val.lport  = ntohl(val)  & 0x0000FFFF;224	f->mask.lport = ntohl(mask) & 0x0000FFFF;225 226	return 0;227};228 229static const struct cxgb4_match_field cxgb4_tcp_fields[] = {230	{ .off = 0, .val = cxgb4_fill_l4_ports },231	{ .val = NULL }232};233 234static const struct cxgb4_match_field cxgb4_udp_fields[] = {235	{ .off = 0, .val = cxgb4_fill_l4_ports },236	{ .val = NULL }237};238 239struct cxgb4_next_header {240	/* Offset, shift, and mask added to beginning of the header241	 * to get to next header.  Useful when using a header242	 * field's value to jump to next header such as IHL field243	 * in IPv4 header.244	 */245	struct tc_u32_sel_hdr sel;246	struct tc_u32_key key;247	/* location of jump to make */248	const struct cxgb4_match_field *jump;249};250 251/* Accept a rule with a jump to transport layer header based on IHL field in252 * IPv4 header.253 */254static const struct cxgb4_next_header cxgb4_ipv4_jumps[] = {255	{256		/* TCP Jump */257		.sel = {258			.off = 0,259			.offoff = 0,260			.offshift = 6,261			.offmask = cpu_to_be16(0x0f00),262		},263		.key = {264			.off = 8,265			.val = cpu_to_be32(0x00060000),266			.mask = cpu_to_be32(0x00ff0000),267		},268		.jump = cxgb4_tcp_fields,269	},270	{271		/* UDP Jump */272		.sel = {273			.off = 0,274			.offoff = 0,275			.offshift = 6,276			.offmask = cpu_to_be16(0x0f00),277		},278		.key = {279			.off = 8,280			.val = cpu_to_be32(0x00110000),281			.mask = cpu_to_be32(0x00ff0000),282		},283		.jump = cxgb4_udp_fields,284	},285	{ .jump = NULL },286};287 288/* Accept a rule with a jump directly past the 40 Bytes of IPv6 fixed header289 * to get to transport layer header.290 */291static const struct cxgb4_next_header cxgb4_ipv6_jumps[] = {292	{293		/* TCP Jump */294		.sel = {295			.off = 40,296			.offoff = 0,297			.offshift = 0,298			.offmask = 0,299		},300		.key = {301			.off = 4,302			.val = cpu_to_be32(0x00000600),303			.mask = cpu_to_be32(0x0000ff00),304		},305		.jump = cxgb4_tcp_fields,306	},307	{308		/* UDP Jump */309		.sel = {310			.off = 40,311			.offoff = 0,312			.offshift = 0,313			.offmask = 0,314		},315		.key = {316			.off = 4,317			.val = cpu_to_be32(0x00001100),318			.mask = cpu_to_be32(0x0000ff00),319		},320		.jump = cxgb4_udp_fields,321	},322	{ .jump = NULL },323};324 325struct cxgb4_link {326	const struct cxgb4_match_field *match_field;  /* Next header */327	struct ch_filter_specification fs; /* Match spec associated with link */328	u32 link_handle;         /* Knode handle associated with the link */329	unsigned long *tid_map;  /* Bitmap for filter tids */330};331 332struct cxgb4_tc_u32_table {333	unsigned int size;          /* number of entries in table */334	struct cxgb4_link table[] __counted_by(size); /* Jump table */335};336#endif /* __CXGB4_TC_U32_PARSE_H */337