1219820Sjeff/*-
2219820Sjeff * Copyright (c) 2010 Isilon Systems, Inc.
3219820Sjeff * Copyright (c) 2010 iX Systems, Inc.
4219820Sjeff * Copyright (c) 2010 Panasas, Inc.
5271127Shselasky * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6219820Sjeff * All rights reserved.
7219820Sjeff *
8219820Sjeff * Redistribution and use in source and binary forms, with or without
9219820Sjeff * modification, are permitted provided that the following conditions
10219820Sjeff * are met:
11219820Sjeff * 1. Redistributions of source code must retain the above copyright
12219820Sjeff *    notice unmodified, this list of conditions, and the following
13219820Sjeff *    disclaimer.
14219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
15219820Sjeff *    notice, this list of conditions and the following disclaimer in the
16219820Sjeff *    documentation and/or other materials provided with the distribution.
17219820Sjeff *
18219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20219820Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21219820Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22219820Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24219820Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25219820Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26219820Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27219820Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28219820Sjeff */
29219820Sjeff#ifndef	_LINUX_NETDEVICE_H_
30219820Sjeff#define	_LINUX_NETDEVICE_H_
31219820Sjeff
32219820Sjeff#include <linux/types.h>
33219820Sjeff
34219820Sjeff#include <sys/socket.h>
35219820Sjeff
36219820Sjeff#include <net/if_types.h>
37219820Sjeff#include <net/if.h>
38219820Sjeff#include <net/if_var.h>
39219820Sjeff#include <net/if_dl.h>
40219820Sjeff
41219820Sjeff#include <linux/completion.h>
42219820Sjeff#include <linux/device.h>
43219820Sjeff#include <linux/workqueue.h>
44219820Sjeff#include <linux/net.h>
45219820Sjeff#include <linux/notifier.h>
46219820Sjeff
47219820Sjeffstruct net {
48219820Sjeff};
49219820Sjeff
50219820Sjeffextern struct net init_net;
51219820Sjeff
52219820Sjeff#define	MAX_ADDR_LEN		20
53219820Sjeff
54219820Sjeff#define	net_device	ifnet
55219820Sjeff
56219820Sjeff#define	dev_get_by_index(n, idx)	ifnet_byindex_ref((idx))
57219820Sjeff#define	dev_hold(d)	if_ref((d))
58219820Sjeff#define	dev_put(d)	if_rele((d))
59219820Sjeff
60219820Sjeff#define	netif_running(dev)	!!((dev)->if_drv_flags & IFF_DRV_RUNNING)
61219820Sjeff#define	netif_oper_up(dev)	!!((dev)->if_flags & IFF_UP)
62219820Sjeff#define	netif_carrier_ok(dev)	netif_running(dev)
63219820Sjeff
64219820Sjeffstatic inline void *
65219820Sjeffnetdev_priv(const struct net_device *dev)
66219820Sjeff{
67219820Sjeff	return (dev->if_softc);
68219820Sjeff}
69219820Sjeff
70219820Sjeffstatic inline void
71219820Sjeff_handle_ifnet_link_event(void *arg, struct ifnet *ifp, int linkstate)
72219820Sjeff{
73219820Sjeff	struct notifier_block *nb;
74219820Sjeff
75219820Sjeff	nb = arg;
76219820Sjeff	if (linkstate == LINK_STATE_UP)
77219820Sjeff		nb->notifier_call(nb, NETDEV_UP, ifp);
78219820Sjeff	else
79219820Sjeff		nb->notifier_call(nb, NETDEV_DOWN, ifp);
80219820Sjeff}
81219820Sjeff
82219820Sjeffstatic inline void
83219820Sjeff_handle_ifnet_arrival_event(void *arg, struct ifnet *ifp)
84219820Sjeff{
85219820Sjeff	struct notifier_block *nb;
86219820Sjeff
87219820Sjeff	nb = arg;
88219820Sjeff	nb->notifier_call(nb, NETDEV_REGISTER, ifp);
89219820Sjeff}
90219820Sjeff
91219820Sjeffstatic inline void
92219820Sjeff_handle_ifnet_departure_event(void *arg, struct ifnet *ifp)
93219820Sjeff{
94219820Sjeff	struct notifier_block *nb;
95219820Sjeff
96219820Sjeff	nb = arg;
97219820Sjeff	nb->notifier_call(nb, NETDEV_UNREGISTER, ifp);
98219820Sjeff}
99219820Sjeff
100271127Shselaskystatic inline void
101271127Shselasky_handle_iflladdr_event(void *arg, struct ifnet *ifp)
102271127Shselasky{
103271127Shselasky	struct notifier_block *nb;
104271127Shselasky
105271127Shselasky	nb = arg;
106271127Shselasky	nb->notifier_call(nb, NETDEV_CHANGEADDR, ifp);
107271127Shselasky}
108271127Shselasky
109271127Shselaskystatic inline void
110271127Shselasky_handle_ifaddr_event(void *arg, struct ifnet *ifp)
111271127Shselasky{
112271127Shselasky	struct notifier_block *nb;
113271127Shselasky
114271127Shselasky	nb = arg;
115271127Shselasky	nb->notifier_call(nb, NETDEV_CHANGEIFADDR, ifp);
116271127Shselasky}
117271127Shselasky
118219820Sjeffstatic inline int
119219820Sjeffregister_netdevice_notifier(struct notifier_block *nb)
120219820Sjeff{
121219820Sjeff
122219820Sjeff	nb->tags[NETDEV_UP] = EVENTHANDLER_REGISTER(
123219820Sjeff	    ifnet_link_event, _handle_ifnet_link_event, nb, 0);
124219820Sjeff	nb->tags[NETDEV_REGISTER] = EVENTHANDLER_REGISTER(
125219820Sjeff	    ifnet_arrival_event, _handle_ifnet_arrival_event, nb, 0);
126219820Sjeff	nb->tags[NETDEV_UNREGISTER] = EVENTHANDLER_REGISTER(
127219820Sjeff	    ifnet_departure_event, _handle_ifnet_departure_event, nb, 0);
128271127Shselasky	nb->tags[NETDEV_CHANGEADDR] = EVENTHANDLER_REGISTER(
129271127Shselasky	    iflladdr_event, _handle_iflladdr_event, nb, 0);
130271127Shselasky
131219820Sjeff	return (0);
132219820Sjeff}
133219820Sjeff
134219820Sjeffstatic inline int
135271127Shselaskyregister_inetaddr_notifier(struct notifier_block *nb)
136271127Shselasky{
137271127Shselasky
138271127Shselasky        nb->tags[NETDEV_CHANGEIFADDR] = EVENTHANDLER_REGISTER(
139271127Shselasky            ifaddr_event, _handle_ifaddr_event, nb, 0);
140271127Shselasky        return (0);
141271127Shselasky}
142271127Shselasky
143271127Shselaskystatic inline int
144219820Sjeffunregister_netdevice_notifier(struct notifier_block *nb)
145219820Sjeff{
146219820Sjeff
147219820Sjeff        EVENTHANDLER_DEREGISTER(ifnet_link_event, nb->tags[NETDEV_UP]);
148219820Sjeff        EVENTHANDLER_DEREGISTER(ifnet_arrival_event, nb->tags[NETDEV_REGISTER]);
149219820Sjeff        EVENTHANDLER_DEREGISTER(ifnet_departure_event,
150219820Sjeff	    nb->tags[NETDEV_UNREGISTER]);
151271127Shselasky        EVENTHANDLER_DEREGISTER(iflladdr_event,
152271127Shselasky            nb->tags[NETDEV_CHANGEADDR]);
153271127Shselasky
154219820Sjeff	return (0);
155219820Sjeff}
156219820Sjeff
157271127Shselaskystatic inline int
158271127Shselaskyunregister_inetaddr_notifier(struct notifier_block *nb)
159271127Shselasky{
160271127Shselasky
161271127Shselasky        EVENTHANDLER_DEREGISTER(ifaddr_event,
162271127Shselasky            nb->tags[NETDEV_CHANGEIFADDR]);
163271127Shselasky
164271127Shselasky        return (0);
165271127Shselasky}
166271127Shselasky
167271127Shselasky
168219820Sjeff#define	rtnl_lock()
169219820Sjeff#define	rtnl_unlock()
170219820Sjeff
171219820Sjeffstatic inline int
172219820Sjeffdev_mc_delete(struct net_device *dev, void *addr, int alen, int all)
173219820Sjeff{
174219820Sjeff	struct sockaddr_dl sdl;
175219820Sjeff
176219820Sjeff	if (alen > sizeof(sdl.sdl_data))
177219820Sjeff		return (-EINVAL);
178219820Sjeff	memset(&sdl, 0, sizeof(sdl));
179219820Sjeff	sdl.sdl_len = sizeof(sdl);
180219820Sjeff	sdl.sdl_family = AF_LINK;
181219820Sjeff	sdl.sdl_alen = alen;
182219820Sjeff	memcpy(&sdl.sdl_data, addr, alen);
183219820Sjeff
184219820Sjeff	return -if_delmulti(dev, (struct sockaddr *)&sdl);
185219820Sjeff}
186219820Sjeff
187219820Sjeffstatic inline int
188219820Sjeffdev_mc_add(struct net_device *dev, void *addr, int alen, int newonly)
189219820Sjeff{
190219820Sjeff	struct sockaddr_dl sdl;
191219820Sjeff
192219820Sjeff	if (alen > sizeof(sdl.sdl_data))
193219820Sjeff		return (-EINVAL);
194219820Sjeff	memset(&sdl, 0, sizeof(sdl));
195219820Sjeff	sdl.sdl_len = sizeof(sdl);
196219820Sjeff	sdl.sdl_family = AF_LINK;
197219820Sjeff	sdl.sdl_alen = alen;
198219820Sjeff	memcpy(&sdl.sdl_data, addr, alen);
199219820Sjeff
200219820Sjeff	return -if_addmulti(dev, (struct sockaddr *)&sdl, NULL);
201219820Sjeff}
202219820Sjeff
203219820Sjeff#endif	/* _LINUX_NETDEVICE_H_ */
204