summaryrefslogtreecommitdiff
path: root/sys/net/if_switch.h
blob: 951bb7889ef49445eaaf3b4f5344c22ac340ba0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*	$OpenBSD: if_switch.h,v 1.5 2016/10/28 09:01:49 rzalamena Exp $	*/

/*
 * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
 * Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _NET_IF_SWITCH_H_
#define _NET_IF_SWITCH_H_

/* capabilities for switch(4) */
#define SWITCH_CAP_STP		0x0001
#define SWITCH_CAP_LEARNING	0x0002
#define SWITCH_CAP_OFP		0x0004

#ifdef _KERNEL

struct switch_field_tunnel {
	uint32_t	 tun_af;
	struct in_addr	 tun_ipv4_src;
	struct in_addr	 tun_ipv4_dst;
	struct in6_addr	 tun_ipv6_src;
	struct in6_addr	 tun_ipv6_dst;
	uint64_t	 tun_key;
};

struct switch_field_ether {
	uint8_t		 eth_src[ETHER_ADDR_LEN];
	uint8_t		 __pad_eth_src[2];
	uint8_t		 eth_dst[ETHER_ADDR_LEN];
	uint8_t		 __pad_eth_dst[2];
	uint16_t	 eth_type;
	uint8_t		 __pad_eth_type[2];
};

struct switch_field_vlan {
	uint16_t	 vlan_tpid;
	uint16_t	 vlan_vid;
	uint16_t	 vlan_pcp;
	uint8_t		 __pad_vlan_pcp[2];
};

struct switch_field_ipv4 {
	uint32_t	 ipv4_src;
	uint32_t	 ipv4_dst;
	uint8_t		 ipv4_proto;
	uint8_t		 ipv4_tos;
	uint8_t		 ipv4_ttl;
	uint8_t		 ipv4_frag;
};

struct switch_field_ipv6 {
	struct in6_addr	 ipv6_src;
	struct in6_addr	 ipv6_dst;
	uint32_t	 ipv6_flow_label;
	uint8_t		 ipv6_nxt;
	uint8_t		 ipv6_tclass;
	uint8_t		 ipv6_hlimit;
	uint8_t		 ipv6_frag;
};

struct switch_field_arp {
	uint16_t	 _arp_op;
	uint8_t		 __pad_arp_op[2];
	uint8_t		 arp_sha[ETHER_ADDR_LEN];
	uint8_t		 __pad_arp_sha[2];
	uint8_t		 arp_tha[ETHER_ADDR_LEN];
	uint8_t		 __pad_arp_tha[2];
	uint32_t	 arp_sip;
	uint32_t	 arp_tip;
};

struct switch_field_nd6 {
	struct in6_addr	 nd6_target;
	uint8_t		 nd6_lladdr[ETHER_ADDR_LEN];
	uint8_t		 __pad_nd6_lladdr[2];
};

struct switch_field_icmpv4 {
	uint8_t		 icmpv4_type;
	uint8_t		 icmpv4_code;
	uint8_t		 __pad[2];
};

struct switch_field_icmpv6 {
	uint8_t		 icmpv6_type;
	uint8_t		 icmpv6_code;
	uint8_t		 __pad[2];
};

struct switch_field_tcp {
	uint16_t	 tcp_src;
	uint16_t	 tcp_dst;
	uint8_t		 tcp_flags;
	uint8_t		 __pad[3];
};

struct switch_field_udp {
	uint16_t	 udp_src;
	uint16_t	 udp_dst;
};

struct switch_field_sctp {
	uint16_t	 sctp_src;
	uint16_t	 sctp_dst;
};

union switch_field {
	struct switch_field_tunnel	 swfcl_tunnel;
	struct switch_field_ether	 swfcl_ether;
	struct switch_field_vlan	 swfcl_vlan;
	struct switch_field_ipv4	 swfcl_ipv4;
	struct switch_field_ipv6	 swfcl_ipv6;
	struct switch_field_arp		 swfcl_arp;
	struct switch_field_nd6		 swfcl_nd6;
	struct switch_field_icmpv4	 swfcl_icmpv4;
	struct switch_field_icmpv6	 swfcl_icmpv6;
	struct switch_field_tcp		 swfcl_tcp;
	struct switch_field_udp		 swfcl_udp;
	struct switch_field_sctp	 swfcl_sctp;
};

struct switch_flow_classify {
	uint64_t			 swfcl_flow_hash;

	/*
	 * Pipeline field on OpenFlow switch specific
	 */
	uint64_t			 swfcl_metadata;
	uint64_t			 swfcl_cookie;
	uint8_t				 swfcl_table_id;

	/*
	 * Classify field without protocol headers
	 */
	uint32_t			 swfcl_in_port;

	/*
	 * Classify field from protocol headers
	 */
	struct switch_field_tunnel	*swfcl_tunnel;
	struct switch_field_ether	*swfcl_ether;
	struct switch_field_vlan	*swfcl_vlan;
	struct switch_field_ipv4	*swfcl_ipv4;
	struct switch_field_ipv6	*swfcl_ipv6;
	struct switch_field_arp		*swfcl_arp;
	struct switch_field_nd6		*swfcl_nd6;
	struct switch_field_icmpv4	*swfcl_icmpv4;
	struct switch_field_icmpv6	*swfcl_icmpv6;
	struct switch_field_tcp		*swfcl_tcp;
	struct switch_field_udp		*swfcl_udp;
	struct switch_field_sctp	*swfcl_sctp;
};

struct switch_softc;

struct switch_port {
	TAILQ_ENTRY(switch_port)	 swpo_list_next;
	TAILQ_ENTRY(switch_port)	 swpo_fwdp_next;
	uint32_t			 swpo_port_no;
	uint32_t			 swpo_ifindex;
	struct timespec			 swpo_appended;
	struct switch_softc		*swpo_switch;
	uint32_t			 swpo_flags;
	void				*swpo_dhcookie;
	void				(*swop_bk_start)(struct ifnet *);
};

TAILQ_HEAD(switch_fwdp_queue, switch_port);

struct switch_dev {
	struct mbuf_queue	 swdev_outq;
	struct selinfo		 swdev_rsel;
	struct mutex		 swdev_rsel_mtx;
	struct selinfo		 swdev_wsel;
	struct mutex		 swdev_wsel_mtx;
	int			 swdev_waiting;
	void			(*swdev_init)(struct switch_softc *);
	int			(*swdev_input)(struct switch_softc *,
				    struct mbuf *);
	int			(*swdev_output)(struct switch_softc *,
				    struct mbuf *);
};

struct switch_softc {
	struct ifnet			 sc_if;
	int				 sc_unit;
	uint32_t			 sc_capabilities;
	struct switch_dev		*sc_swdev;		/* char device */
	struct bstp_state		*sc_stp;		/* STP state */
	struct swofp_ofs		*sc_ofs;		/* OpenFlow */
	TAILQ_HEAD(,switch_port)	 sc_swpo_list; 		/* port */
	LIST_ENTRY(switch_softc)	 sc_switch_next; 	/* switch link */
	void				(*switch_process_forward)(
	    struct switch_softc *, struct switch_flow_classify *,
	    struct mbuf *);
};

/* if_switch.c */
struct switch_softc
	*switch_lookup(int);
void	 switch_port_egress(struct switch_softc *, struct switch_fwdp_queue *,
	    struct mbuf *);
int	 switch_swfcl_dup(struct switch_flow_classify *,
	    struct switch_flow_classify *);
void	 switch_swfcl_free(struct switch_flow_classify *);
struct mbuf
	*switch_flow_classifier(struct mbuf *, uint32_t,
	    struct switch_flow_classify *);

/* switchctl.c */
void	 switch_dev_destroy(struct switch_softc *);

/* in switchofp.c */
void	 swofp_attach(void);
int	 swofp_create(struct switch_softc *);
int	 swofp_init(struct switch_softc *);
void	 swofp_destroy(struct switch_softc *);
int	 swofp_ioctl(struct ifnet *, unsigned long, caddr_t);
uint32_t
	 swofp_assign_portno(struct switch_softc *, uint32_t);

#endif /* _KERNEL */
#endif /* _NET_IF_SWITCH_H_ */