xref: /titanic_51/usr/src/uts/common/io/aggr/aggr_recv.c (revision da14cebe459d3275048785f25bd869cb09b5307f)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5f12af565Snd99603  * Common Development and Distribution License (the "License").
6f12af565Snd99603  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22d62bc4baSyz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * IEEE 802.3ad Link Aggregation - Receive
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * Implements the collector function.
307c478bd9Sstevel@tonic-gate  * Manages the RX resources exposed by a link aggregation group.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
357c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
367c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
377c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
387c478bd9Sstevel@tonic-gate #include <sys/byteorder.h>
397c478bd9Sstevel@tonic-gate #include <sys/aggr.h>
407c478bd9Sstevel@tonic-gate #include <sys/aggr_impl.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate static void
43*da14cebeSEric Cheng aggr_mac_rx(mac_handle_t lg_mh, mac_resource_handle_t mrh, mblk_t *mp)
44*da14cebeSEric Cheng {
45*da14cebeSEric Cheng 	if (mrh == NULL) {
46*da14cebeSEric Cheng 		mac_rx(lg_mh, mrh, mp);
47*da14cebeSEric Cheng 	} else {
48*da14cebeSEric Cheng 		aggr_pseudo_rx_ring_t	*ring = (aggr_pseudo_rx_ring_t *)mrh;
49*da14cebeSEric Cheng 		mac_rx_ring(lg_mh, ring->arr_rh, mp, ring->arr_gen);
50*da14cebeSEric Cheng 	}
51*da14cebeSEric Cheng }
52*da14cebeSEric Cheng 
53*da14cebeSEric Cheng void
54*da14cebeSEric Cheng aggr_recv_lacp(aggr_port_t *port, mac_resource_handle_t mrh, mblk_t *mp)
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate 	aggr_grp_t *grp = port->lp_grp;
577c478bd9Sstevel@tonic-gate 
58d62bc4baSyz147064 	/* in promiscuous mode, send copy of packet up */
597c478bd9Sstevel@tonic-gate 	if (grp->lg_promisc) {
607c478bd9Sstevel@tonic-gate 		mblk_t *nmp = copymsg(mp);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 		if (nmp != NULL)
63*da14cebeSEric Cheng 			aggr_mac_rx(grp->lg_mh, mrh, nmp);
647c478bd9Sstevel@tonic-gate 	}
657c478bd9Sstevel@tonic-gate 
66*da14cebeSEric Cheng 	aggr_lacp_rx_enqueue(port, mp);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Callback function invoked by MAC service module when packets are
717c478bd9Sstevel@tonic-gate  * made available by a MAC port.
727c478bd9Sstevel@tonic-gate  */
73*da14cebeSEric Cheng /* ARGSUSED */
747c478bd9Sstevel@tonic-gate void
75*da14cebeSEric Cheng aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
76*da14cebeSEric Cheng     boolean_t loopback)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	aggr_port_t *port = (aggr_port_t *)arg;
797c478bd9Sstevel@tonic-gate 	aggr_grp_t *grp = port->lp_grp;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
82*da14cebeSEric Cheng 		aggr_mac_rx(grp->lg_mh, mrh, mp);
837c478bd9Sstevel@tonic-gate 	} else {
847c478bd9Sstevel@tonic-gate 		mblk_t *cmp, *last, *head;
857c478bd9Sstevel@tonic-gate 		struct ether_header *ehp;
867c478bd9Sstevel@tonic-gate 		uint16_t sap;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 		/* filter out slow protocol packets (LACP & Marker) */
897c478bd9Sstevel@tonic-gate 		last = NULL;
907c478bd9Sstevel@tonic-gate 		head = cmp = mp;
917c478bd9Sstevel@tonic-gate 		while (cmp != NULL) {
927c478bd9Sstevel@tonic-gate 			if (MBLKL(cmp) < sizeof (struct ether_header)) {
937c478bd9Sstevel@tonic-gate 				/* packet too short */
947c478bd9Sstevel@tonic-gate 				if (head == cmp) {
957c478bd9Sstevel@tonic-gate 					/* no packets accumulated */
967c478bd9Sstevel@tonic-gate 					head = cmp->b_next;
977c478bd9Sstevel@tonic-gate 					cmp->b_next = NULL;
987c478bd9Sstevel@tonic-gate 					freemsg(cmp);
997c478bd9Sstevel@tonic-gate 					cmp = head;
1007c478bd9Sstevel@tonic-gate 				} else {
1017c478bd9Sstevel@tonic-gate 					/* send up accumulated packets */
1027c478bd9Sstevel@tonic-gate 					last->b_next = NULL;
103*da14cebeSEric Cheng 					if (port->lp_collector_enabled) {
104*da14cebeSEric Cheng 						aggr_mac_rx(grp->lg_mh, mrh,
105*da14cebeSEric Cheng 						    head);
106*da14cebeSEric Cheng 					} else {
107f12af565Snd99603 						freemsgchain(head);
108*da14cebeSEric Cheng 					}
1097c478bd9Sstevel@tonic-gate 					head = cmp->b_next;
1107c478bd9Sstevel@tonic-gate 					cmp->b_next = NULL;
1117c478bd9Sstevel@tonic-gate 					freemsg(cmp);
1127c478bd9Sstevel@tonic-gate 					cmp = head;
1137c478bd9Sstevel@tonic-gate 					last = NULL;
1147c478bd9Sstevel@tonic-gate 				}
1157c478bd9Sstevel@tonic-gate 				continue;
1167c478bd9Sstevel@tonic-gate 			}
1177c478bd9Sstevel@tonic-gate 			ehp = (struct ether_header *)cmp->b_rptr;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 			sap = ntohs(ehp->ether_type);
1207c478bd9Sstevel@tonic-gate 			if (sap == ETHERTYPE_SLOW) {
1217c478bd9Sstevel@tonic-gate 				/*
1227c478bd9Sstevel@tonic-gate 				 * LACP or Marker packet. Send up pending
1237c478bd9Sstevel@tonic-gate 				 * chain, and send LACP/Marker packet
1247c478bd9Sstevel@tonic-gate 				 * to LACP subsystem.
1257c478bd9Sstevel@tonic-gate 				 */
1267c478bd9Sstevel@tonic-gate 				if (head == cmp) {
1277c478bd9Sstevel@tonic-gate 					/* first packet of chain */
1287c478bd9Sstevel@tonic-gate 					ASSERT(last == NULL);
1297c478bd9Sstevel@tonic-gate 					head = cmp->b_next;
1307c478bd9Sstevel@tonic-gate 					cmp->b_next = NULL;
131*da14cebeSEric Cheng 					aggr_recv_lacp(port, mrh, cmp);
1327c478bd9Sstevel@tonic-gate 					cmp = head;
1337c478bd9Sstevel@tonic-gate 				} else {
1347c478bd9Sstevel@tonic-gate 					/* previously accumulated packets */
1357c478bd9Sstevel@tonic-gate 					ASSERT(last != NULL);
1367c478bd9Sstevel@tonic-gate 					/* send up non-LACP packets */
1377c478bd9Sstevel@tonic-gate 					last->b_next = NULL;
138*da14cebeSEric Cheng 					if (port->lp_collector_enabled) {
139*da14cebeSEric Cheng 						aggr_mac_rx(grp->lg_mh, mrh,
140*da14cebeSEric Cheng 						    head);
141*da14cebeSEric Cheng 					} else {
142f12af565Snd99603 						freemsgchain(head);
143*da14cebeSEric Cheng 					}
1447c478bd9Sstevel@tonic-gate 					/* unlink and pass up LACP packets */
1457c478bd9Sstevel@tonic-gate 					head = cmp->b_next;
1467c478bd9Sstevel@tonic-gate 					cmp->b_next = NULL;
147*da14cebeSEric Cheng 					aggr_recv_lacp(port, mrh, cmp);
1487c478bd9Sstevel@tonic-gate 					cmp = head;
1497c478bd9Sstevel@tonic-gate 					last = NULL;
1507c478bd9Sstevel@tonic-gate 				}
1517c478bd9Sstevel@tonic-gate 			} else {
1527c478bd9Sstevel@tonic-gate 				last = cmp;
1537c478bd9Sstevel@tonic-gate 				cmp = cmp->b_next;
1547c478bd9Sstevel@tonic-gate 			}
1557c478bd9Sstevel@tonic-gate 		}
1567c478bd9Sstevel@tonic-gate 		if (head != NULL) {
1577c478bd9Sstevel@tonic-gate 			if (port->lp_collector_enabled)
158*da14cebeSEric Cheng 				aggr_mac_rx(grp->lg_mh, mrh, head);
1597c478bd9Sstevel@tonic-gate 			else
160f12af565Snd99603 				freemsgchain(head);
1617c478bd9Sstevel@tonic-gate 		}
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate }
164