3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/atm_if.c,v 1.5 1999/08/28 00:48:35 peter Exp $
33 * ATM interface management
37 #include "kern_include.h"
42 static int atm_physif_ioctl (int, caddr_t
, caddr_t
);
43 static int atm_netif_rtdel (struct radix_node
*, void *);
44 static int atm_if_ioctl (struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
45 static int atm_ifparse (char *, char *, int, int *);
50 static int (*atm_ifouttbl
[AF_MAX
+1])
51 (struct ifnet
*, KBuffer
*, struct sockaddr
*)
56 * Register an ATM physical interface
58 * Each ATM device interface must register itself here upon completing
59 * its internal initialization. This applies to both linked and loaded
60 * device drivers. The interface must be registered before a signalling
61 * manager can be attached.
64 * cup pointer to interface's common unit structure
65 * name pointer to device name string
66 * sdp pointer to interface's stack services
69 * 0 registration successful
70 * errno registration failed - reason indicated
74 atm_physif_register(Cmn_unit
*cup
, char *name
, struct stack_defn
*sdp
)
79 * See if we need to be initialized
85 * Make sure we're not already registered
87 if (cup
->cu_flags
& CUF_REGISTER
) {
94 * Make sure an interface is only registered once
96 for (pip
= atm_interface_head
; pip
!= NULL
; pip
= pip
->pif_next
) {
97 if ((cup
->cu_unit
== pip
->pif_unit
) &&
98 (strcmp(name
, pip
->pif_name
) == 0)) {
105 * Fill in physical interface parameters
108 pip
->pif_name
= name
;
109 pip
->pif_unit
= cup
->cu_unit
;
110 pip
->pif_flags
= PIF_UP
;
111 pip
->pif_services
= sdp
;
112 pip
->pif_ioctl
= atm_physif_ioctl
;
115 * Link in the interface and mark us registered
117 LINK2TAIL(pip
, struct atm_pif
, atm_interface_head
, pif_next
);
118 cup
->cu_flags
|= CUF_REGISTER
;
126 * De-register an ATM physical interface
128 * Each ATM interface must de-register itself before downing the interface.
129 * The interface's signalling manager will be detached and any network
130 * interface and VCC control blocks will be freed.
133 * cup pointer to interface's common unit structure
136 * 0 de-registration successful
137 * errno de-registration failed - reason indicated
141 atm_physif_deregister(Cmn_unit
*cup
)
143 struct atm_pif
*pip
= (struct atm_pif
*)&cup
->cu_pif
;
150 * Detach and deregister, if needed
152 if ((cup
->cu_flags
& CUF_REGISTER
)) {
155 * Detach from signalling manager
157 if (pip
->pif_sigmgr
!= NULL
) {
158 err
= atm_sigmgr_detach(pip
);
159 if (err
&& (err
!= ENOENT
)) {
166 * Make sure signalling manager is detached
168 if (pip
->pif_sigmgr
!= NULL
) {
176 UNLINK(pip
, struct atm_pif
, atm_interface_head
, pif_next
);
178 cup
->cu_flags
&= ~CUF_REGISTER
;
182 * Free all of our network interfaces
184 atm_physif_freenifs(pip
);
187 * Free unit's vcc information
203 * Free all network interfaces on a physical interface
206 * pip pointer to physical interface structure
213 atm_physif_freenifs(struct atm_pif
*pip
)
215 struct atm_nif
*nip
= pip
->pif_nif
;
221 * atm_nif_detach zeros pointers - save so we can
224 struct atm_nif
*nipp
= nip
->nif_pnext
;
227 * Clean up network i/f trails
229 atm_nif_detach ( nip
);
230 atm_free ((caddr_t
)nip
);
242 * Handle physical interface ioctl's
244 * See <netatm/atm_ioctl.h> for definitions.
246 * Called from a critical section.
249 * code Ioctl function (sub)code
250 * data Data block. On input contains command,
251 * on output, contains results
252 * arg Optional code specific arguments
255 * 0 Request processed successfully
256 * errno Request failed - reason code
260 atm_physif_ioctl(int code
, caddr_t data
, caddr_t arg
)
262 struct atminfreq
*aip
= (struct atminfreq
*)data
;
263 struct atmsetreq
*asr
= (struct atmsetreq
*)data
;
271 caddr_t buf
= aip
->air_buf_addr
;
272 struct air_phy_stat_rsp
*apsp
;
273 struct air_int_rsp apr
;
274 struct air_netif_rsp anr
;
275 struct air_cfg_rsp acr
;
276 int count
, len
, buf_len
= aip
->air_buf_len
;
278 char ifname
[2*IFNAMSIZ
];
279 struct in_ifaddr
*ia
;
280 struct sockaddr_dl
*sdl
;
282 switch ( aip
->air_opcode
) {
286 * Get physical interface information
288 aip
= (struct atminfreq
*)data
;
289 pip
= (struct atm_pif
*)arg
;
292 * Make sure there's room in user buffer
294 if (aip
->air_buf_len
< sizeof(apr
)) {
300 * Fill in info to be returned
302 KM_ZERO((caddr_t
)&apr
, sizeof(apr
));
303 smp
= pip
->pif_sigmgr
;
304 sip
= pip
->pif_siginst
;
305 ksnprintf(apr
.anp_intf
, sizeof(apr
.anp_intf
),
306 "%s%d", pip
->pif_name
, pip
->pif_unit
);
309 strcpy(apr
.anp_nif_pref
, /* XXX: strings */
310 pip
->pif_nif
->nif_if
.if_dname
);
315 nip
= nip
->nif_pnext
;
319 ATM_ADDR_COPY(&sip
->si_addr
, &apr
.anp_addr
);
320 ATM_ADDR_COPY(&sip
->si_subaddr
, &apr
.anp_subaddr
);
321 apr
.anp_sig_proto
= smp
->sm_proto
;
322 apr
.anp_sig_state
= sip
->si_state
;
326 * Copy data to user buffer
328 err
= copyout((caddr_t
)&apr
, aip
->air_buf_addr
, sizeof(apr
));
333 * Update buffer pointer/count
335 aip
->air_buf_addr
+= sizeof(apr
);
336 aip
->air_buf_len
-= sizeof(apr
);
341 * Get network interface information
343 aip
= (struct atminfreq
*)data
;
344 nip
= (struct atm_nif
*)arg
;
349 * Make sure there's room in user buffer
351 if (aip
->air_buf_len
< sizeof(anr
)) {
357 * Fill in info to be returned
359 KM_ZERO((caddr_t
)&anr
, sizeof(anr
));
360 ksnprintf(anr
.anp_intf
, sizeof(anr
.anp_intf
),
361 "%s", ifp
->if_xname
);
364 anr
.anp_proto_addr
= *ia
->ia_ifa
.ifa_addr
;
366 ksnprintf(anr
.anp_phy_intf
, sizeof(anr
.anp_phy_intf
),
367 "%s%d", pip
->pif_name
, pip
->pif_unit
);
370 * Copy data to user buffer
372 err
= copyout((caddr_t
)&anr
, aip
->air_buf_addr
, sizeof(anr
));
377 * Update buffer pointer/count
379 aip
->air_buf_addr
+= sizeof(anr
);
380 aip
->air_buf_len
-= sizeof(anr
);
385 * Get per interface statistics
387 pip
= (struct atm_pif
*)arg
;
390 ksnprintf ( ifname
, sizeof(ifname
),
391 "%s%d", pip
->pif_name
, pip
->pif_unit
);
394 * Cast response into users buffer
396 apsp
= (struct air_phy_stat_rsp
*)buf
;
401 len
= sizeof ( struct air_phy_stat_rsp
);
406 * Copy interface name into response
408 if ((err
= copyout ( ifname
, apsp
->app_intf
, IFNAMSIZ
)) != 0)
414 if ((err
= copyout(&pip
->pif_ipdus
, &apsp
->app_ipdus
,
415 len
- sizeof(apsp
->app_intf
))) != 0)
419 * Adjust buffer elements
424 aip
->air_buf_addr
= buf
;
425 aip
->air_buf_len
= buf_len
;
430 * Set NIF - allow user to configure 1 or more logical
431 * interfaces per physical interface.
435 * Get pointer to physical interface structure from
438 pip
= (struct atm_pif
*)arg
;
439 cup
= (Cmn_unit
*)pip
;
442 * Sanity check - are we already connected to something?
444 if ( pip
->pif_sigmgr
)
451 * Free any previously allocated NIFs
453 atm_physif_freenifs(pip
);
456 * Add list of interfaces
458 for ( count
= 0; count
< asr
->asr_nif_cnt
; count
++ )
460 nip
= (struct atm_nif
*)atm_allocate(cup
->cu_nif_pool
);
464 * Destroy any successful nifs
466 atm_physif_freenifs(pip
);
474 strcpy ( nip
->nif_name
, asr
->asr_nif_pref
);
475 nip
->nif_sel
= count
;
477 if_initname(ifp
, nip
->nif_name
, count
);
478 ifp
->if_mtu
= ATM_NIF_MTU
;
479 ifp
->if_flags
= IFF_UP
| IFF_BROADCAST
| IFF_RUNNING
;
480 ifp
->if_output
= atm_ifoutput
;
481 ifp
->if_ioctl
= atm_if_ioctl
;
482 ifp
->if_snd
.ifq_maxlen
= ifqmaxlen
;
484 * Set if_type and if_baudrate
486 ifp
->if_type
= IFT_ATM
;
487 switch ( cup
->cu_config
.ac_media
) {
489 ifp
->if_baudrate
= 100000000;
492 ifp
->if_baudrate
= 140000000;
497 ifp
->if_baudrate
= 155000000;
500 panic("AIOCF_SETNIF: unknown media");
503 if ((err
= atm_nif_attach(nip
, NULL
)) != 0) {
504 atm_free ( (caddr_t
)nip
);
507 * Destroy any successful nifs
509 atm_physif_freenifs(pip
);
513 * Set macaddr in <Link> address
516 sdl
= IF_LLSOCKADDR(ifp
);
517 sdl
->sdl_type
= IFT_ETHER
;
518 sdl
->sdl_alen
= ifp
->if_addrlen
;
519 bcopy ( (caddr_t
)&cup
->cu_config
.ac_macaddr
,
520 LLADDR(sdl
), ifp
->if_addrlen
);
526 * Get adapter configuration information
528 aip
= (struct atminfreq
*)data
;
529 pip
= (struct atm_pif
*)arg
;
530 cup
= (Cmn_unit
*)pip
;
531 acp
= &cup
->cu_config
;
534 * Make sure there's room in user buffer
536 if (aip
->air_buf_len
< sizeof(acr
)) {
542 * Fill in info to be returned
544 KM_ZERO((caddr_t
)&acr
, sizeof(acr
));
545 ksnprintf(acr
.acp_intf
, sizeof(acr
.acp_intf
),
546 "%s%d", pip
->pif_name
, pip
->pif_unit
);
547 KM_COPY((caddr_t
)acp
, (caddr_t
)&acr
.acp_cfg
,
551 * Copy data to user buffer
553 err
= copyout((caddr_t
)&acr
, aip
->air_buf_addr
,
559 * Update buffer pointer/count
561 aip
->air_buf_addr
+= sizeof(acr
);
562 aip
->air_buf_len
-= sizeof(acr
);
567 * Pass off to device-specific handler
569 cup
= (Cmn_unit
*)arg
;
573 err
= (*cup
->cu_ioctl
)(code
, data
, arg
);
585 * Register a Network Convergence Module
587 * Each ATM network convergence module must register itself here before
588 * it will receive network interface status notifications.
591 * ncp pointer to network convergence definition structure
594 * 0 registration successful
595 * errno registration failed - reason indicated
599 atm_netconv_register(struct atm_ncm
*ncp
)
605 * See if we need to be initialized
611 * Validate protocol family
613 if (ncp
->ncm_family
> AF_MAX
) {
619 * Ensure no duplicates
621 for (tdp
= atm_netconv_head
; tdp
!= NULL
; tdp
= tdp
->ncm_next
) {
622 if (tdp
->ncm_family
== ncp
->ncm_family
) {
631 LINK2TAIL(ncp
, struct atm_ncm
, atm_netconv_head
, ncm_next
);
634 * Add new interface output function
636 atm_ifouttbl
[ncp
->ncm_family
] = ncp
->ncm_ifoutput
;
644 * De-register an ATM Network Convergence Module
646 * Each ATM network convergence provider must de-register its registered
647 * service(s) before terminating. Specifically, loaded kernel modules
648 * must de-register their services before unloading themselves.
651 * ncp pointer to network convergence definition structure
654 * 0 de-registration successful
655 * errno de-registration failed - reason indicated
659 atm_netconv_deregister(struct atm_ncm
*ncp
)
666 * Remove module from list
668 UNLINKF(ncp
, struct atm_ncm
, atm_netconv_head
, ncm_next
, found
);
676 * Remove module's interface output function
678 atm_ifouttbl
[ncp
->ncm_family
] = NULL
;
686 * Attach an ATM Network Interface
688 * Before an ATM network interface can be used by the system, the owning
689 * device interface must attach the network interface using this function.
690 * The physical interface for this network interface must have been previously
691 * registered (using atm_interface_register). The network interface will be
692 * added to the kernel's interface list and to the physical interface's list.
693 * The caller is responsible for initializing the control block fields.
696 * nip pointer to atm network interface control block
699 * 0 attach successful
700 * errno attach failed - reason indicated
704 atm_nif_attach(struct atm_nif
*nip
, lwkt_serialize_t serializer
)
706 struct atm_pif
*pip
, *pip2
;
716 * Verify physical interface is registered
718 for (pip2
= atm_interface_head
; pip2
!= NULL
; pip2
= pip2
->pif_next
) {
722 if ((pip
== NULL
) || (pip2
== NULL
)) {
728 * Add to system interface list
730 if_attach(ifp
, serializer
);
733 * Add to physical interface list
735 LINK2TAIL(nip
, struct atm_nif
, pip
->pif_nif
, nif_pnext
);
738 * Notify network convergence modules of new network i/f
740 for (ncp
= atm_netconv_head
; ncp
; ncp
= ncp
->ncm_next
) {
743 err
= (*ncp
->ncm_stat
)(NCM_ATTACH
, nip
, 0);
757 * Detach an ATM Network Interface
759 * Before an ATM network interface control block can be freed, all kernel
760 * references to/from this block must be released. This function will delete
761 * all routing references to the interface and free all interface addresses
762 * for the interface. The network interface will then be removed from the
763 * kernel's interface list and from the owning physical interface's list.
764 * The caller is responsible for free'ing the control block.
767 * nip pointer to atm network interface control block
774 atm_nif_detach(struct atm_nif
*nip
)
778 struct ifnet
*ifp
= &nip
->nif_if
;
780 struct in_ifaddr
*ia
;
781 struct radix_node_head
*rnh
;
786 * Notify convergence modules of network i/f demise
788 for (ncp
= atm_netconv_head
; ncp
; ncp
= ncp
->ncm_next
) {
789 (*ncp
->ncm_stat
)(NCM_DETACH
, nip
, 0);
793 * Mark interface down
798 * Free all interface routes and addresses
805 /* Delete interface route */
808 /* Remove interface address from queues */
810 ifa_ifunlink(ifa
, ifp
);
813 /* Free interface address */
818 * Delete all remaining routes using this interface
819 * Unfortuneatly the only way to do this is to slog through
820 * the entire routing table looking for routes which point
821 * to this interface...oh well...
823 for (i
= 1; i
<= AF_MAX
; i
++) {
824 if ((rnh
= rt_tables
[mycpuid
][i
]) == NULL
)
826 rnh
->rnh_walktree(rnh
, atm_netif_rtdel
, ifp
);
830 * Remove from system interface list (ie. if_detach())
832 TAILQ_REMOVE(&ifnet
, ifp
, if_link
);
835 * Remove from physical interface list
837 UNLINK(nip
, struct atm_nif
, nip
->nif_pif
->pif_nif
, nif_pnext
);
844 * Delete Routes for a Network Interface
846 * Called for each routing entry via the rnh->rnh_walktree() call above
847 * to delete all route entries referencing a detaching network interface.
850 * rn pointer to node in the routing table
851 * arg argument passed to rnh->rnh_walktree() - detaching interface
855 * errno failed - reason indicated
859 atm_netif_rtdel(struct radix_node
*rn
, void *arg
)
861 struct rtentry
*rt
= (struct rtentry
*)rn
;
862 struct ifnet
*ifp
= arg
;
865 if (rt
->rt_ifp
== ifp
) {
868 * Protect (sorta) against walktree recursion problems
871 if ((rt
->rt_flags
& RTF_UP
) == 0)
874 err
= rtrequest(RTM_DELETE
, rt_key(rt
), rt
->rt_gateway
,
875 rt_mask(rt
), rt
->rt_flags
,
878 log(LOG_WARNING
, "atm_netif_rtdel: error %d\n", err
);
887 * Set an ATM Network Interface address
889 * This is called from a device interface when processing an SIOCSIFADDR
890 * ioctl request. We just notify all convergence modules of the new address
891 * and hope everyone has non-overlapping interests, since if someone reports
892 * an error we don't go back and tell everyone to undo the change.
895 * nip pointer to atm network interface control block
896 * ifa pointer to new interface address
900 * errno set failed - reason indicated
904 atm_nif_setaddr(struct atm_nif
*nip
, struct ifaddr
*ifa
)
911 * Notify convergence modules of network i/f change
913 for (ncp
= atm_netconv_head
; ncp
; ncp
= ncp
->ncm_next
) {
914 err
= (*ncp
->ncm_stat
)(NCM_SETADDR
, nip
, (int)ifa
);
925 * ATM Interface Packet Output
927 * All ATM network interfaces must have their ifnet if_output address set to
928 * this function. Since no existing network layer code is to be modified
929 * for ATM support, this function serves as the hook to allow network output
930 * packets to be assigned to their proper outbound VCC. Each network address
931 * family which is to be supported over ATM must be assigned an output
932 * packet processing function via atm_netconv_register().
935 * ifp pointer to ifnet structure
936 * m pointer to packet buffer chain to be output
937 * dst pointer to packet's network destination address
940 * 0 packet queued to interface
941 * errno output failed - reason indicated
945 atm_ifoutput_serialized(struct ifnet
*ifp
, KBuffer
*m
, struct sockaddr
*dst
,
948 u_short fam
= dst
->sa_family
;
949 int (*func
)(struct ifnet
*, KBuffer
*,
953 * Validate address family
957 return (EAFNOSUPPORT
);
961 * Hand packet off for dst-to-VCC mapping
963 func
= atm_ifouttbl
[fam
];
966 return (EAFNOSUPPORT
);
968 return ((*func
)(ifp
, m
, dst
));
972 atm_ifoutput(struct ifnet
*ifp
, KBuffer
*m
, struct sockaddr
*dst
,
977 ifnet_serialize_tx(ifp
);
978 error
= atm_ifoutput_serialized(ifp
, m
, dst
, rt
);
979 ifnet_deserialize_tx(ifp
);
985 * Handle interface ioctl requests.
988 * ifp pointer to network interface structure
990 * data arguments to/from ioctl
996 atm_if_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
998 struct ifreq
*ifr
= (struct ifreq
*)data
;
999 struct atm_nif
*nip
= (struct atm_nif
*)ifp
;
1006 KM_COPY ( (caddr_t
)&(nip
->nif_pif
->pif_macaddr
),
1007 (caddr_t
)ifr
->ifr_addr
.sa_data
,
1008 sizeof(struct mac_addr
) );
1012 error
= atm_nif_setaddr ( nip
, (struct ifaddr
*)data
);
1013 ifp
->if_flags
|= IFF_UP
| IFF_RUNNING
| IFF_BROADCAST
;
1017 *(short *)data
= ifp
->if_flags
;
1034 * Parse interface name
1036 * Parses an interface name string into a name and a unit component.
1039 * name pointer to interface name string
1040 * namep address to store interface name
1041 * size size available at namep
1042 * unitp address to store interface unit number
1050 atm_ifparse(char *name
, char *namep
, int size
, int *unitp
)
1053 int len
= 0, unit
= 0;
1056 * Separate supplied string into name and unit parts.
1061 if (*cp
>= '0' && *cp
<= '9')
1068 while (*cp
&& *cp
>= '0' && *cp
<= '9')
1069 unit
= 10 * unit
+ *cp
++ - '0';
1078 * Locate ATM physical interface via name
1080 * Uses the supplied interface name string to locate a registered
1081 * ATM physical interface.
1084 * name pointer to interface name string
1087 * 0 interface not found
1088 * else pointer to atm physical interface structure
1092 atm_pifname(char *name
)
1094 struct atm_pif
*pip
;
1101 if (atm_ifparse(name
, n
, sizeof(n
), &unit
))
1105 * Look for the physical interface
1107 for (pip
= atm_interface_head
; pip
; pip
= pip
->pif_next
) {
1108 if ((pip
->pif_unit
== unit
) && (strcmp(pip
->pif_name
, n
) == 0))
1117 * Locate ATM network interface via name
1119 * Uses the supplied interface name string to locate an ATM network interface.
1122 * name pointer to interface name string
1125 * 0 interface not found
1126 * else pointer to atm network interface structure
1130 atm_nifname(char *name
)
1132 struct atm_pif
*pip
;
1133 struct atm_nif
*nip
;
1140 if (atm_ifparse(name
, n
, sizeof(n
), &unit
))
1144 * Search thru each physical interface
1146 for (pip
= atm_interface_head
; pip
; pip
= pip
->pif_next
) {
1148 * Looking for network interface
1150 for (nip
= pip
->pif_nif
; nip
; nip
= nip
->nif_pnext
) {
1151 struct ifnet
*ifp
= (struct ifnet
*)nip
;
1152 if ((ifp
->if_dunit
== unit
) &&
1153 (strcmp(ifp
->if_dname
, n
) == 0))