1 /* $NetBSD: if_agrsubr.c,v 1.7 2007/08/02 12:37:47 yamt Exp $ */
4 * Copyright (c)2005 YAMAMOTO Takashi,
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: if_agrsubr.c,v 1.7 2007/08/02 12:37:47 yamt Exp $");
35 #include <sys/param.h>
36 #include <sys/callout.h>
37 #include <sys/malloc.h>
38 #include <sys/systm.h>
39 #include <sys/types.h>
40 #include <sys/queue.h>
41 #include <sys/sockio.h>
45 #include <net/agr/if_agrvar_impl.h>
46 #include <net/agr/if_agrsubr.h>
49 TAILQ_ENTRY(agr_mc_entry
) ame_q
;
51 struct agr_ifreq ame_ifr
; /* XXX waste */
54 static struct agr_mc_entry
*agr_mc_lookup(struct agr_multiaddrs
*,
55 const struct sockaddr
*);
56 static int agrport_mc_add_callback(struct agr_port
*, void *);
57 static int agrport_mc_del_callback(struct agr_port
*, void *);
58 static int agrmc_mc_add_callback(struct agr_mc_entry
*, void *);
59 static int agrmc_mc_del_callback(struct agr_mc_entry
*, void *);
61 static int agr_mc_add(struct agr_multiaddrs
*, const struct sockaddr
*);
62 static int agr_mc_del(struct agr_multiaddrs
*, const struct sockaddr
*);
65 agr_mc_purgeall(struct agr_softc
*sc
, struct agr_multiaddrs
*ama
)
67 struct agr_mc_entry
*ame
;
70 while ((ame
= TAILQ_FIRST(&ama
->ama_addrs
)) != NULL
) {
71 error
= agr_port_foreach(sc
,
72 agrport_mc_del_callback
, &ame
->ame_ifr
);
75 printf("%s: error %d\n", __func__
, error
);
77 TAILQ_REMOVE(&ama
->ama_addrs
, ame
, ame_q
);
85 agr_mc_init(struct agr_softc
*sc
, struct agr_multiaddrs
*ama
)
88 TAILQ_INIT(&ama
->ama_addrs
);
93 /* ==================== */
95 static struct agr_mc_entry
*
96 agr_mc_lookup(struct agr_multiaddrs
*ama
, const struct sockaddr
*sa
)
98 struct agr_mc_entry
*ame
;
100 TAILQ_FOREACH(ame
, &ama
->ama_addrs
, ame_q
) {
101 if (!memcmp(&ame
->ame_ifr
.ifr_ss
, sa
, sa
->sa_len
))
109 agr_mc_foreach(struct agr_multiaddrs
*ama
,
110 int (*func
)(struct agr_mc_entry
*, void *), void *arg
)
112 struct agr_mc_entry
*ame
;
115 TAILQ_FOREACH(ame
, &ama
->ama_addrs
, ame_q
) {
116 error
= (*func
)(ame
, arg
);
119 * XXX how to recover?
120 * we can try to restore setting, but it can also fail..
130 agr_mc_add(struct agr_multiaddrs
*ama
, const struct sockaddr
*sa
)
132 struct agr_mc_entry
*ame
;
134 ame
= agr_mc_lookup(ama
, sa
);
140 ame
= malloc(sizeof(*ame
), M_DEVBUF
, M_NOWAIT
| M_ZERO
);
144 memcpy(&ame
->ame_ifr
.ifr_ss
, sa
, sa
->sa_len
);
146 TAILQ_INSERT_TAIL(&ama
->ama_addrs
, ame
, ame_q
);
152 agr_mc_del(struct agr_multiaddrs
*ama
, const struct sockaddr
*sa
)
154 struct agr_mc_entry
*ame
;
156 ame
= agr_mc_lookup(ama
, sa
);
161 if (ame
->ame_refcnt
> 0)
164 TAILQ_REMOVE(&ama
->ama_addrs
, ame
, ame_q
);
170 /* ==================== */
173 agr_port_foreach(struct agr_softc
*sc
,
174 int (*func
)(struct agr_port
*, void *), void *arg
)
176 struct agr_port
*port
;
179 TAILQ_FOREACH(port
, &sc
->sc_ports
, port_q
) {
180 if ((port
->port_flags
& (AGRPORT_LARVAL
| AGRPORT_DETACHING
))) {
183 error
= (func
)(port
, arg
);
186 * XXX how to recover?
187 * we can try to restore setting, but it can also fail..
196 /* ==================== */
199 agrmc_mc_add_callback(struct agr_mc_entry
*ame
, void *arg
)
202 return agrport_mc_add_callback(arg
, &ame
->ame_ifr
);
206 agrmc_mc_del_callback(struct agr_mc_entry
*ame
, void *arg
)
209 return agrport_mc_del_callback(arg
, &ame
->ame_ifr
);
213 agr_configmulti_port(struct agr_multiaddrs
*ama
, struct agr_port
*port
,
217 return agr_mc_foreach(ama
,
218 add
? agrmc_mc_add_callback
: agrmc_mc_del_callback
, port
);
221 /* -------------------- */
224 agrport_mc_add_callback(struct agr_port
*port
, void *arg
)
227 return agrport_ioctl(port
, SIOCADDMULTI
, arg
);
231 agrport_mc_del_callback(struct agr_port
*port
, void *arg
)
234 return agrport_ioctl(port
, SIOCDELMULTI
, arg
);
238 agr_configmulti_ifreq(struct agr_softc
*sc
, struct agr_multiaddrs
*ama
,
239 struct ifreq
*ifr
, bool add
)
244 error
= agr_mc_add(ama
, ifreq_getaddr(SIOCADDMULTI
, ifr
));
246 error
= agr_mc_del(ama
, ifreq_getaddr(SIOCDELMULTI
, ifr
));
248 if (error
!= ENETRESET
)
251 return agr_port_foreach(sc
,
252 add
? agrport_mc_add_callback
: agrport_mc_del_callback
, ifr
);
255 /* ==================== */
258 agr_port_getmedia(struct agr_port
*port
, u_int
*media
, u_int
*status
)
260 struct ifmediareq ifmr
;
263 memset(&ifmr
, 0, sizeof(ifmr
));
265 error
= agrport_ioctl(port
, SIOCGIFMEDIA
, (void *)&ifmr
);
268 *media
= ifmr
.ifm_active
;
269 *status
= ifmr
.ifm_status
;