Deleted Added
full compact
ip_mroute.c (133720) ip_mroute.c (133874)
1/*
2 * IP multicast forwarding procedures
3 *
4 * Written by David Waitzman, BBN Labs, August 1988.
5 * Modified by Steve Deering, Stanford, February 1989.
6 * Modified by Mark J. Steiglitz, Stanford, May, 1991
7 * Modified by Van Jacobson, LBL, January 1993
8 * Modified by Ajit Thyagarajan, PARC, August 1993
9 * Modified by Bill Fenner, PARC, April 1995
10 * Modified by Ahmed Helmy, SGI, June 1996
11 * Modified by George Edmond Eddy (Rusty), ISI, February 1998
12 * Modified by Pavlin Radoslavov, USC/ISI, May 1998, August 1999, October 2000
13 * Modified by Hitoshi Asaeda, WIDE, August 2000
14 * Modified by Pavlin Radoslavov, ICSI, October 2002
15 *
16 * MROUTING Revision: 3.5
17 * and PIM-SMv2 and PIM-DM support, advanced API support,
18 * bandwidth metering and signaling
19 *
1/*
2 * IP multicast forwarding procedures
3 *
4 * Written by David Waitzman, BBN Labs, August 1988.
5 * Modified by Steve Deering, Stanford, February 1989.
6 * Modified by Mark J. Steiglitz, Stanford, May, 1991
7 * Modified by Van Jacobson, LBL, January 1993
8 * Modified by Ajit Thyagarajan, PARC, August 1993
9 * Modified by Bill Fenner, PARC, April 1995
10 * Modified by Ahmed Helmy, SGI, June 1996
11 * Modified by George Edmond Eddy (Rusty), ISI, February 1998
12 * Modified by Pavlin Radoslavov, USC/ISI, May 1998, August 1999, October 2000
13 * Modified by Hitoshi Asaeda, WIDE, August 2000
14 * Modified by Pavlin Radoslavov, ICSI, October 2002
15 *
16 * MROUTING Revision: 3.5
17 * and PIM-SMv2 and PIM-DM support, advanced API support,
18 * bandwidth metering and signaling
19 *
20 * $FreeBSD: head/sys/netinet/ip_mroute.c 133720 2004-08-14 15:32:40Z dwmalone $
20 * $FreeBSD: head/sys/netinet/ip_mroute.c 133874 2004-08-16 18:32:07Z rwatson $
21 */
22
23#include "opt_mac.h"
24#include "opt_mrouting.h"
25
26#ifdef PIM
27#define _PIM_VT 1
28#endif

--- 97 unchanged lines hidden (view full) ---

126
127static struct callout expire_upcalls_ch;
128
129#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
130#define UPCALL_EXPIRE 6 /* number of timeouts */
131
132/*
133 * Define the token bucket filter structures
21 */
22
23#include "opt_mac.h"
24#include "opt_mrouting.h"
25
26#ifdef PIM
27#define _PIM_VT 1
28#endif

--- 97 unchanged lines hidden (view full) ---

126
127static struct callout expire_upcalls_ch;
128
129#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
130#define UPCALL_EXPIRE 6 /* number of timeouts */
131
132/*
133 * Define the token bucket filter structures
134 * tbftable -> each vif has one of these for storing info
134 * tbftable -> each vif has one of these for storing info
135 */
136
137static struct tbf tbftable[MAXVIFS];
138#define TBF_REPROCESS (hz / 100) /* 100x / second */
139
140/*
141 * 'Interfaces' associated with decapsulator (so we can tell
142 * packets that went through it from ones that get reflected

--- 13 unchanged lines hidden (view full) ---

156 sizeof(struct ip) >> 2, IPVERSION,
157#else
158 IPVERSION, sizeof(struct ip) >> 2,
159#endif
160 0, /* tos */
161 sizeof(struct ip), /* total length */
162 0, /* id */
163 0, /* frag offset */
135 */
136
137static struct tbf tbftable[MAXVIFS];
138#define TBF_REPROCESS (hz / 100) /* 100x / second */
139
140/*
141 * 'Interfaces' associated with decapsulator (so we can tell
142 * packets that went through it from ones that get reflected

--- 13 unchanged lines hidden (view full) ---

156 sizeof(struct ip) >> 2, IPVERSION,
157#else
158 IPVERSION, sizeof(struct ip) >> 2,
159#endif
160 0, /* tos */
161 sizeof(struct ip), /* total length */
162 0, /* id */
163 0, /* frag offset */
164 ENCAP_TTL, ENCAP_PROTO,
164 ENCAP_TTL, ENCAP_PROTO,
165 0, /* checksum */
166};
167
168/*
169 * Bandwidth meter variables and constants
170 */
171static MALLOC_DEFINE(M_BWMETER, "bwmeter", "multicast upcall bw meters");
172/*

--- 42 unchanged lines hidden (view full) ---

215 IPVERSION,
216#else
217 IPVERSION,
218 sizeof(struct ip) >> 2,
219#endif
220 0, /* tos */
221 sizeof(struct ip), /* total length */
222 0, /* id */
165 0, /* checksum */
166};
167
168/*
169 * Bandwidth meter variables and constants
170 */
171static MALLOC_DEFINE(M_BWMETER, "bwmeter", "multicast upcall bw meters");
172/*

--- 42 unchanged lines hidden (view full) ---

215 IPVERSION,
216#else
217 IPVERSION,
218 sizeof(struct ip) >> 2,
219#endif
220 0, /* tos */
221 sizeof(struct ip), /* total length */
222 0, /* id */
223 0, /* frag offset */
223 0, /* frag offset */
224 ENCAP_TTL,
225 IPPROTO_PIM,
226 0, /* checksum */
227};
228
229static struct pim_encap_pimhdr pim_encap_pimhdr = {
230 {
231 PIM_MAKE_VT(PIM_VERSION, PIM_REGISTER), /* PIM vers and message type */

--- 715 unchanged lines hidden (view full) ---

947 (struct protosw *)&mroute_encap_protosw, NULL);
948
949 if (encap_cookie == NULL) {
950 printf("ip_mroute: unable to attach encap\n");
951 VIF_UNLOCK();
952 return EIO; /* XXX */
953 }
954 for (i = 0; i < MAXVIFS; ++i) {
224 ENCAP_TTL,
225 IPPROTO_PIM,
226 0, /* checksum */
227};
228
229static struct pim_encap_pimhdr pim_encap_pimhdr = {
230 {
231 PIM_MAKE_VT(PIM_VERSION, PIM_REGISTER), /* PIM vers and message type */

--- 715 unchanged lines hidden (view full) ---

947 (struct protosw *)&mroute_encap_protosw, NULL);
948
949 if (encap_cookie == NULL) {
950 printf("ip_mroute: unable to attach encap\n");
951 VIF_UNLOCK();
952 return EIO; /* XXX */
953 }
954 for (i = 0; i < MAXVIFS; ++i) {
955 if_initname(&multicast_decap_if[i], "mdecap", i);
955 if_initname(&multicast_decap_if[i], "mdecap", i);
956 }
957 }
958 /*
959 * Set interface to fake encapsulator interface
960 */
961 ifp = &multicast_decap_if[vifcp->vifc_vifi];
962 /*
963 * Prepare cached route entry

--- 56 unchanged lines hidden (view full) ---

1020
1021 /* Adjust numvifs up if the vifi is higher than numvifs */
1022 if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
1023
1024 VIF_UNLOCK();
1025
1026 if (mrtdebug)
1027 log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %d\n",
956 }
957 }
958 /*
959 * Set interface to fake encapsulator interface
960 */
961 ifp = &multicast_decap_if[vifcp->vifc_vifi];
962 /*
963 * Prepare cached route entry

--- 56 unchanged lines hidden (view full) ---

1020
1021 /* Adjust numvifs up if the vifi is higher than numvifs */
1022 if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
1023
1024 VIF_UNLOCK();
1025
1026 if (mrtdebug)
1027 log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %d\n",
1028 vifcp->vifc_vifi,
1028 vifcp->vifc_vifi,
1029 (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr),
1030 (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",
1031 (u_long)ntohl(vifcp->vifc_rmt_addr.s_addr),
1032 vifcp->vifc_threshold,
1029 (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr),
1030 (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",
1031 (u_long)ntohl(vifcp->vifc_rmt_addr.s_addr),
1032 vifcp->vifc_threshold,
1033 vifcp->vifc_rate_limit);
1033 vifcp->vifc_rate_limit);
1034
1035 return 0;
1036}
1037
1038/*
1039 * Delete a vif from the vif table
1040 */
1041static int

--- 118 unchanged lines hidden (view full) ---

1160 mfccp->mfcc_parent);
1161
1162 update_mfc_params(rt, mfccp);
1163 MFC_UNLOCK();
1164 VIF_UNLOCK();
1165 return 0;
1166 }
1167
1034
1035 return 0;
1036}
1037
1038/*
1039 * Delete a vif from the vif table
1040 */
1041static int

--- 118 unchanged lines hidden (view full) ---

1160 mfccp->mfcc_parent);
1161
1162 update_mfc_params(rt, mfccp);
1163 MFC_UNLOCK();
1164 VIF_UNLOCK();
1165 return 0;
1166 }
1167
1168 /*
1168 /*
1169 * Find the entry for which the upcall was made and update
1170 */
1171 hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
1172 for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
1173
1174 if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
1175 (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
1176 (rt->mfc_stall != NULL)) {
1169 * Find the entry for which the upcall was made and update
1170 */
1171 hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
1172 for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
1173
1174 if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
1175 (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
1176 (rt->mfc_stall != NULL)) {
1177
1177
1178 if (nstl++)
1179 log(LOG_ERR, "add_mfc %s o %lx g %lx p %x dbx %p\n",
1180 "multiple kernel entries",
1181 (u_long)ntohl(mfccp->mfcc_origin.s_addr),
1182 (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
1183 mfccp->mfcc_parent, (void *)rt->mfc_stall);
1184
1185 if (mrtdebug & DEBUG_MFC)

--- 24 unchanged lines hidden (view full) ---

1210 * It is possible that an entry is being inserted without an upcall
1211 */
1212 if (nstl == 0) {
1213 if (mrtdebug & DEBUG_MFC)
1214 log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n",
1215 hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr),
1216 (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
1217 mfccp->mfcc_parent);
1178 if (nstl++)
1179 log(LOG_ERR, "add_mfc %s o %lx g %lx p %x dbx %p\n",
1180 "multiple kernel entries",
1181 (u_long)ntohl(mfccp->mfcc_origin.s_addr),
1182 (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
1183 mfccp->mfcc_parent, (void *)rt->mfc_stall);
1184
1185 if (mrtdebug & DEBUG_MFC)

--- 24 unchanged lines hidden (view full) ---

1210 * It is possible that an entry is being inserted without an upcall
1211 */
1212 if (nstl == 0) {
1213 if (mrtdebug & DEBUG_MFC)
1214 log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n",
1215 hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr),
1216 (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
1217 mfccp->mfcc_parent);
1218
1218
1219 for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) {
1220 if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
1221 (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
1222 init_mfc_params(rt, mfccp);
1223 if (rt->mfc_expire)
1224 nexpire[hash]--;
1225 rt->mfc_expire = 0;
1226 break; /* XXX */
1227 }
1228 }
1229 if (rt == NULL) { /* no upcall, so make a new entry */
1230 rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
1231 if (rt == NULL) {
1232 MFC_UNLOCK();
1233 VIF_UNLOCK();
1234 return ENOBUFS;
1235 }
1219 for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) {
1220 if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
1221 (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
1222 init_mfc_params(rt, mfccp);
1223 if (rt->mfc_expire)
1224 nexpire[hash]--;
1225 rt->mfc_expire = 0;
1226 break; /* XXX */
1227 }
1228 }
1229 if (rt == NULL) { /* no upcall, so make a new entry */
1230 rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
1231 if (rt == NULL) {
1232 MFC_UNLOCK();
1233 VIF_UNLOCK();
1234 return ENOBUFS;
1235 }
1236
1236
1237 init_mfc_params(rt, mfccp);
1238 rt->mfc_expire = 0;
1239 rt->mfc_stall = NULL;
1237 init_mfc_params(rt, mfccp);
1238 rt->mfc_expire = 0;
1239 rt->mfc_stall = NULL;
1240
1240
1241 rt->mfc_bw_meter = NULL;
1242 /* insert new entry at head of hash chain */
1243 rt->mfc_next = mfctable[hash];
1244 mfctable[hash] = rt;
1245 }
1246 }
1247 MFC_UNLOCK();
1248 VIF_UNLOCK();
1249 return 0;
1250}
1251
1252/*
1253 * Delete an mfc entry
1254 */
1255static int
1256del_mfc(struct mfcctl2 *mfccp)
1257{
1241 rt->mfc_bw_meter = NULL;
1242 /* insert new entry at head of hash chain */
1243 rt->mfc_next = mfctable[hash];
1244 mfctable[hash] = rt;
1245 }
1246 }
1247 MFC_UNLOCK();
1248 VIF_UNLOCK();
1249 return 0;
1250}
1251
1252/*
1253 * Delete an mfc entry
1254 */
1255static int
1256del_mfc(struct mfcctl2 *mfccp)
1257{
1258 struct in_addr origin;
1259 struct in_addr mcastgrp;
1260 struct mfc *rt;
1261 struct mfc **nptr;
1262 u_long hash;
1258 struct in_addr origin;
1259 struct in_addr mcastgrp;
1260 struct mfc *rt;
1261 struct mfc **nptr;
1262 u_long hash;
1263 struct bw_meter *list;
1264
1265 origin = mfccp->mfcc_origin;
1266 mcastgrp = mfccp->mfcc_mcastgrp;
1267
1268 if (mrtdebug & DEBUG_MFC)
1269 log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n",
1270 (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr));

--- 210 unchanged lines hidden (view full) ---

1481 rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
1482 if (rt == NULL)
1483 goto fail;
1484 /* Make a copy of the header to send to the user level process */
1485 mm = m_copy(mb0, 0, hlen);
1486 if (mm == NULL)
1487 goto fail1;
1488
1263 struct bw_meter *list;
1264
1265 origin = mfccp->mfcc_origin;
1266 mcastgrp = mfccp->mfcc_mcastgrp;
1267
1268 if (mrtdebug & DEBUG_MFC)
1269 log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n",
1270 (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr));

--- 210 unchanged lines hidden (view full) ---

1481 rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
1482 if (rt == NULL)
1483 goto fail;
1484 /* Make a copy of the header to send to the user level process */
1485 mm = m_copy(mb0, 0, hlen);
1486 if (mm == NULL)
1487 goto fail1;
1488
1489 /*
1490 * Send message to routing daemon to install
1489 /*
1490 * Send message to routing daemon to install
1491 * a route into the kernel table
1492 */
1491 * a route into the kernel table
1492 */
1493
1493
1494 im = mtod(mm, struct igmpmsg *);
1495 im->im_msgtype = IGMPMSG_NOCACHE;
1496 im->im_mbz = 0;
1497 im->im_vif = vifi;
1498
1499 mrtstat.mrts_upcalls++;
1500
1501 k_igmpsrc.sin_addr = ip->ip_src;

--- 52 unchanged lines hidden (view full) ---

1554 VIF_UNLOCK();
1555 return 0;
1556 }
1557
1558 /* Add this entry to the end of the queue */
1559 *p = rte;
1560 }
1561
1494 im = mtod(mm, struct igmpmsg *);
1495 im->im_msgtype = IGMPMSG_NOCACHE;
1496 im->im_mbz = 0;
1497 im->im_vif = vifi;
1498
1499 mrtstat.mrts_upcalls++;
1500
1501 k_igmpsrc.sin_addr = ip->ip_src;

--- 52 unchanged lines hidden (view full) ---

1554 VIF_UNLOCK();
1555 return 0;
1556 }
1557
1558 /* Add this entry to the end of the queue */
1559 *p = rte;
1560 }
1561
1562 rte->m = mb0;
1563 rte->ifp = ifp;
1562 rte->m = mb0;
1563 rte->ifp = ifp;
1564 rte->next = NULL;
1565
1566 MFC_UNLOCK();
1567 VIF_UNLOCK();
1568
1569 return 0;
1564 rte->next = NULL;
1565
1566 MFC_UNLOCK();
1567 VIF_UNLOCK();
1568
1569 return 0;
1570 }
1570 }
1571}
1572
1573/*
1574 * Clean up the cache entry if upcall is not serviced
1575 */
1576static void
1577expire_upcalls(void *unused)
1578{

--- 81 unchanged lines hidden (view full) ---

1660 * If xmt_vif is not -1, send on only the requested vif.
1661 *
1662 * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
1663 */
1664 if (xmt_vif < numvifs) {
1665#ifdef PIM
1666 if (viftable[xmt_vif].v_flags & VIFF_REGISTER)
1667 pim_register_send(ip, viftable + xmt_vif, m, rt);
1571}
1572
1573/*
1574 * Clean up the cache entry if upcall is not serviced
1575 */
1576static void
1577expire_upcalls(void *unused)
1578{

--- 81 unchanged lines hidden (view full) ---

1660 * If xmt_vif is not -1, send on only the requested vif.
1661 *
1662 * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
1663 */
1664 if (xmt_vif < numvifs) {
1665#ifdef PIM
1666 if (viftable[xmt_vif].v_flags & VIFF_REGISTER)
1667 pim_register_send(ip, viftable + xmt_vif, m, rt);
1668 else
1668 else
1669#endif
1670 MC_SEND(ip, viftable + xmt_vif, m);
1671 return 1;
1672 }
1673
1674 /*
1675 * Don't forward if it didn't arrive from the parent vif for its origin.
1676 */
1677 vifi = rt->mfc_parent;
1678 if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) {
1679 /* came in the wrong interface */
1680 if (mrtdebug & DEBUG_FORWARD)
1681 log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n",
1669#endif
1670 MC_SEND(ip, viftable + xmt_vif, m);
1671 return 1;
1672 }
1673
1674 /*
1675 * Don't forward if it didn't arrive from the parent vif for its origin.
1676 */
1677 vifi = rt->mfc_parent;
1678 if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) {
1679 /* came in the wrong interface */
1680 if (mrtdebug & DEBUG_FORWARD)
1681 log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n",
1682 (void *)ifp, vifi, (void *)viftable[vifi].v_ifp);
1682 (void *)ifp, vifi, (void *)viftable[vifi].v_ifp);
1683 ++mrtstat.mrts_wrong_if;
1684 ++rt->mfc_wrong_if;
1685 /*
1686 * If we are doing PIM assert processing, send a message
1687 * to the routing daemon.
1688 *
1689 * XXX: A PIM-SM router needs the WRONGVIF detection so it
1690 * can complete the SPT switch, regardless of the type

--- 254 unchanged lines hidden (view full) ---

1945 m_freem(m);
1946 } else {
1947 tbf_queue(vifp, m);
1948 tbf_process_q(vifp);
1949 }
1950 }
1951}
1952
1683 ++mrtstat.mrts_wrong_if;
1684 ++rt->mfc_wrong_if;
1685 /*
1686 * If we are doing PIM assert processing, send a message
1687 * to the routing daemon.
1688 *
1689 * XXX: A PIM-SM router needs the WRONGVIF detection so it
1690 * can complete the SPT switch, regardless of the type

--- 254 unchanged lines hidden (view full) ---

1945 m_freem(m);
1946 } else {
1947 tbf_queue(vifp, m);
1948 tbf_process_q(vifp);
1949 }
1950 }
1951}
1952
1953/*
1953/*
1954 * adds a packet to the queue at the interface
1955 */
1956static void
1957tbf_queue(struct vif *vifp, struct mbuf *m)
1958{
1959 struct tbf *t = vifp->v_tbf;
1960
1961 VIF_LOCK_ASSERT();

--- 10 unchanged lines hidden (view full) ---

1972 if (m->m_act)
1973 panic("tbf_queue: m_act");
1974#endif
1975 m->m_act = NULL;
1976
1977 t->tbf_q_len++;
1978}
1979
1954 * adds a packet to the queue at the interface
1955 */
1956static void
1957tbf_queue(struct vif *vifp, struct mbuf *m)
1958{
1959 struct tbf *t = vifp->v_tbf;
1960
1961 VIF_LOCK_ASSERT();

--- 10 unchanged lines hidden (view full) ---

1972 if (m->m_act)
1973 panic("tbf_queue: m_act");
1974#endif
1975 m->m_act = NULL;
1976
1977 t->tbf_q_len++;
1978}
1979
1980/*
1980/*
1981 * processes the queue at the interface
1982 */
1983static void
1984tbf_process_q(struct vif *vifp)
1985{
1986 struct tbf *t = vifp->v_tbf;
1987
1988 VIF_LOCK_ASSERT();

--- 20 unchanged lines hidden (view full) ---

2009 }
2010}
2011
2012static void
2013tbf_reprocess_q(void *xvifp)
2014{
2015 struct vif *vifp = xvifp;
2016
1981 * processes the queue at the interface
1982 */
1983static void
1984tbf_process_q(struct vif *vifp)
1985{
1986 struct tbf *t = vifp->v_tbf;
1987
1988 VIF_LOCK_ASSERT();

--- 20 unchanged lines hidden (view full) ---

2009 }
2010}
2011
2012static void
2013tbf_reprocess_q(void *xvifp)
2014{
2015 struct vif *vifp = xvifp;
2016
2017 if (ip_mrouter == NULL)
2017 if (ip_mrouter == NULL)
2018 return;
2019 VIF_LOCK();
2020 tbf_update_tokens(vifp);
2021 tbf_process_q(vifp);
2022 if (vifp->v_tbf->tbf_q_len)
2023 callout_reset(&tbf_reprocess_ch, TBF_REPROCESS, tbf_reprocess_q, vifp);
2024 VIF_UNLOCK();
2025}

--- 55 unchanged lines hidden (view full) ---

2081 * Re-entrancy should not be a problem here, because
2082 * the packets that we send out and are looped back at us
2083 * should get rejected because they appear to come from
2084 * the loopback interface, thus preventing looping.
2085 */
2086 error = ip_output(m, NULL, &ro, IP_FORWARDING, &imo, NULL);
2087
2088 if (mrtdebug & DEBUG_XMIT)
2018 return;
2019 VIF_LOCK();
2020 tbf_update_tokens(vifp);
2021 tbf_process_q(vifp);
2022 if (vifp->v_tbf->tbf_q_len)
2023 callout_reset(&tbf_reprocess_ch, TBF_REPROCESS, tbf_reprocess_q, vifp);
2024 VIF_UNLOCK();
2025}

--- 55 unchanged lines hidden (view full) ---

2081 * Re-entrancy should not be a problem here, because
2082 * the packets that we send out and are looped back at us
2083 * should get rejected because they appear to come from
2084 * the loopback interface, thus preventing looping.
2085 */
2086 error = ip_output(m, NULL, &ro, IP_FORWARDING, &imo, NULL);
2087
2088 if (mrtdebug & DEBUG_XMIT)
2089 log(LOG_DEBUG, "phyint_send on vif %d err %d\n",
2089 log(LOG_DEBUG, "phyint_send on vif %d err %d\n",
2090 (int)(vifp - viftable), error);
2091 }
2092}
2093
2094/* determine the current time and then
2095 * the elapsed time (between the last time and time now)
2096 * in milliseconds & update the no. of tokens in the bucket
2097 */

--- 55 unchanged lines hidden (view full) ---

2153 prio = 55;
2154 break;
2155 }
2156 }
2157 return prio;
2158}
2159
2160/*
2090 (int)(vifp - viftable), error);
2091 }
2092}
2093
2094/* determine the current time and then
2095 * the elapsed time (between the last time and time now)
2096 * in milliseconds & update the no. of tokens in the bucket
2097 */

--- 55 unchanged lines hidden (view full) ---

2153 prio = 55;
2154 break;
2155 }
2156 }
2157 return prio;
2158}
2159
2160/*
2161 * End of token bucket filter modifications
2161 * End of token bucket filter modifications
2162 */
2163
2164static int
2165X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt)
2166{
2167 int error, vifi;
2168
2169 if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
2170 return EOPNOTSUPP;
2171
2172 error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
2173 if (error)
2174 return error;
2162 */
2163
2164static int
2165X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt)
2166{
2167 int error, vifi;
2168
2169 if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
2170 return EOPNOTSUPP;
2171
2172 error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
2173 if (error)
2174 return error;
2175
2175
2176 VIF_LOCK();
2177
2178 if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */
2179 VIF_UNLOCK();
2180 return EADDRNOTAVAIL;
2181 }
2182
2183 if (sopt->sopt_name == IP_RSVP_VIF_ON) {

--- 156 unchanged lines hidden (view full) ---

2340 if (req->bu_flags & BW_UPCALL_UNIT_PACKETS)
2341 flags |= BW_METER_UNIT_PACKETS;
2342 if (req->bu_flags & BW_UPCALL_UNIT_BYTES)
2343 flags |= BW_METER_UNIT_BYTES;
2344 if (req->bu_flags & BW_UPCALL_GEQ)
2345 flags |= BW_METER_GEQ;
2346 if (req->bu_flags & BW_UPCALL_LEQ)
2347 flags |= BW_METER_LEQ;
2176 VIF_LOCK();
2177
2178 if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */
2179 VIF_UNLOCK();
2180 return EADDRNOTAVAIL;
2181 }
2182
2183 if (sopt->sopt_name == IP_RSVP_VIF_ON) {

--- 156 unchanged lines hidden (view full) ---

2340 if (req->bu_flags & BW_UPCALL_UNIT_PACKETS)
2341 flags |= BW_METER_UNIT_PACKETS;
2342 if (req->bu_flags & BW_UPCALL_UNIT_BYTES)
2343 flags |= BW_METER_UNIT_BYTES;
2344 if (req->bu_flags & BW_UPCALL_GEQ)
2345 flags |= BW_METER_GEQ;
2346 if (req->bu_flags & BW_UPCALL_LEQ)
2347 flags |= BW_METER_LEQ;
2348
2348
2349 return flags;
2350}
2349 return flags;
2350}
2351
2351
2352/*
2353 * Add a bw_meter entry
2354 */
2355static int
2356add_bw_upcall(struct bw_upcall *req)
2357{
2358 struct mfc *mfc;
2359 struct timeval delta = { BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC,
2360 BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC };
2361 struct timeval now;
2362 struct bw_meter *x;
2363 uint32_t flags;
2352/*
2353 * Add a bw_meter entry
2354 */
2355static int
2356add_bw_upcall(struct bw_upcall *req)
2357{
2358 struct mfc *mfc;
2359 struct timeval delta = { BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC,
2360 BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC };
2361 struct timeval now;
2362 struct bw_meter *x;
2363 uint32_t flags;
2364
2364
2365 if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
2366 return EOPNOTSUPP;
2365 if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
2366 return EOPNOTSUPP;
2367
2367
2368 /* Test if the flags are valid */
2369 if (!(req->bu_flags & (BW_UPCALL_UNIT_PACKETS | BW_UPCALL_UNIT_BYTES)))
2370 return EINVAL;
2371 if (!(req->bu_flags & (BW_UPCALL_GEQ | BW_UPCALL_LEQ)))
2372 return EINVAL;
2373 if ((req->bu_flags & (BW_UPCALL_GEQ | BW_UPCALL_LEQ))
2374 == (BW_UPCALL_GEQ | BW_UPCALL_LEQ))
2375 return EINVAL;
2368 /* Test if the flags are valid */
2369 if (!(req->bu_flags & (BW_UPCALL_UNIT_PACKETS | BW_UPCALL_UNIT_BYTES)))
2370 return EINVAL;
2371 if (!(req->bu_flags & (BW_UPCALL_GEQ | BW_UPCALL_LEQ)))
2372 return EINVAL;
2373 if ((req->bu_flags & (BW_UPCALL_GEQ | BW_UPCALL_LEQ))
2374 == (BW_UPCALL_GEQ | BW_UPCALL_LEQ))
2375 return EINVAL;
2376
2376
2377 /* Test if the threshold time interval is valid */
2378 if (BW_TIMEVALCMP(&req->bu_threshold.b_time, &delta, <))
2379 return EINVAL;
2377 /* Test if the threshold time interval is valid */
2378 if (BW_TIMEVALCMP(&req->bu_threshold.b_time, &delta, <))
2379 return EINVAL;
2380
2380
2381 flags = compute_bw_meter_flags(req);
2382
2383 /*
2384 * Find if we have already same bw_meter entry
2385 */
2386 MFC_LOCK();
2387 mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
2388 if (mfc == NULL) {

--- 5 unchanged lines hidden (view full) ---

2394 &req->bu_threshold.b_time, ==)) &&
2395 (x->bm_threshold.b_packets == req->bu_threshold.b_packets) &&
2396 (x->bm_threshold.b_bytes == req->bu_threshold.b_bytes) &&
2397 (x->bm_flags & BW_METER_USER_FLAGS) == flags) {
2398 MFC_UNLOCK();
2399 return 0; /* XXX Already installed */
2400 }
2401 }
2381 flags = compute_bw_meter_flags(req);
2382
2383 /*
2384 * Find if we have already same bw_meter entry
2385 */
2386 MFC_LOCK();
2387 mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
2388 if (mfc == NULL) {

--- 5 unchanged lines hidden (view full) ---

2394 &req->bu_threshold.b_time, ==)) &&
2395 (x->bm_threshold.b_packets == req->bu_threshold.b_packets) &&
2396 (x->bm_threshold.b_bytes == req->bu_threshold.b_bytes) &&
2397 (x->bm_flags & BW_METER_USER_FLAGS) == flags) {
2398 MFC_UNLOCK();
2399 return 0; /* XXX Already installed */
2400 }
2401 }
2402
2402
2403 /* Allocate the new bw_meter entry */
2404 x = (struct bw_meter *)malloc(sizeof(*x), M_BWMETER, M_NOWAIT);
2405 if (x == NULL) {
2406 MFC_UNLOCK();
2407 return ENOBUFS;
2408 }
2403 /* Allocate the new bw_meter entry */
2404 x = (struct bw_meter *)malloc(sizeof(*x), M_BWMETER, M_NOWAIT);
2405 if (x == NULL) {
2406 MFC_UNLOCK();
2407 return ENOBUFS;
2408 }
2409
2409
2410 /* Set the new bw_meter entry */
2411 x->bm_threshold.b_time = req->bu_threshold.b_time;
2412 GET_TIME(now);
2413 x->bm_start_time = now;
2414 x->bm_threshold.b_packets = req->bu_threshold.b_packets;
2415 x->bm_threshold.b_bytes = req->bu_threshold.b_bytes;
2416 x->bm_measured.b_packets = 0;
2417 x->bm_measured.b_bytes = 0;
2418 x->bm_flags = flags;
2419 x->bm_time_next = NULL;
2420 x->bm_time_hash = BW_METER_BUCKETS;
2410 /* Set the new bw_meter entry */
2411 x->bm_threshold.b_time = req->bu_threshold.b_time;
2412 GET_TIME(now);
2413 x->bm_start_time = now;
2414 x->bm_threshold.b_packets = req->bu_threshold.b_packets;
2415 x->bm_threshold.b_bytes = req->bu_threshold.b_bytes;
2416 x->bm_measured.b_packets = 0;
2417 x->bm_measured.b_bytes = 0;
2418 x->bm_flags = flags;
2419 x->bm_time_next = NULL;
2420 x->bm_time_hash = BW_METER_BUCKETS;
2421
2421
2422 /* Add the new bw_meter entry to the front of entries for this MFC */
2423 x->bm_mfc = mfc;
2424 x->bm_mfc_next = mfc->mfc_bw_meter;
2425 mfc->mfc_bw_meter = x;
2426 schedule_bw_meter(x, &now);
2427 MFC_UNLOCK();
2422 /* Add the new bw_meter entry to the front of entries for this MFC */
2423 x->bm_mfc = mfc;
2424 x->bm_mfc_next = mfc->mfc_bw_meter;
2425 mfc->mfc_bw_meter = x;
2426 schedule_bw_meter(x, &now);
2427 MFC_UNLOCK();
2428
2428
2429 return 0;
2430}
2431
2432static void
2433free_bw_list(struct bw_meter *list)
2434{
2435 while (list != NULL) {
2436 struct bw_meter *x = list;

--- 7 unchanged lines hidden (view full) ---

2444/*
2445 * Delete one or multiple bw_meter entries
2446 */
2447static int
2448del_bw_upcall(struct bw_upcall *req)
2449{
2450 struct mfc *mfc;
2451 struct bw_meter *x;
2429 return 0;
2430}
2431
2432static void
2433free_bw_list(struct bw_meter *list)
2434{
2435 while (list != NULL) {
2436 struct bw_meter *x = list;

--- 7 unchanged lines hidden (view full) ---

2444/*
2445 * Delete one or multiple bw_meter entries
2446 */
2447static int
2448del_bw_upcall(struct bw_upcall *req)
2449{
2450 struct mfc *mfc;
2451 struct bw_meter *x;
2452
2452
2453 if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
2454 return EOPNOTSUPP;
2453 if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
2454 return EOPNOTSUPP;
2455
2455
2456 MFC_LOCK();
2457 /* Find the corresponding MFC entry */
2458 mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
2459 if (mfc == NULL) {
2460 MFC_UNLOCK();
2461 return EADDRNOTAVAIL;
2462 } else if (req->bu_flags & BW_UPCALL_DELETE_ALL) {
2463 /*
2464 * Delete all bw_meter entries for this mfc
2465 */
2466 struct bw_meter *list;
2456 MFC_LOCK();
2457 /* Find the corresponding MFC entry */
2458 mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
2459 if (mfc == NULL) {
2460 MFC_UNLOCK();
2461 return EADDRNOTAVAIL;
2462 } else if (req->bu_flags & BW_UPCALL_DELETE_ALL) {
2463 /*
2464 * Delete all bw_meter entries for this mfc
2465 */
2466 struct bw_meter *list;
2467
2467
2468 list = mfc->mfc_bw_meter;
2469 mfc->mfc_bw_meter = NULL;
2470 free_bw_list(list);
2471 MFC_UNLOCK();
2472 return 0;
2473 } else { /* Delete a single bw_meter entry */
2474 struct bw_meter *prev;
2475 uint32_t flags = 0;

--- 31 unchanged lines hidden (view full) ---

2507
2508/*
2509 * Perform bandwidth measurement processing that may result in an upcall
2510 */
2511static void
2512bw_meter_receive_packet(struct bw_meter *x, int plen, struct timeval *nowp)
2513{
2514 struct timeval delta;
2468 list = mfc->mfc_bw_meter;
2469 mfc->mfc_bw_meter = NULL;
2470 free_bw_list(list);
2471 MFC_UNLOCK();
2472 return 0;
2473 } else { /* Delete a single bw_meter entry */
2474 struct bw_meter *prev;
2475 uint32_t flags = 0;

--- 31 unchanged lines hidden (view full) ---

2507
2508/*
2509 * Perform bandwidth measurement processing that may result in an upcall
2510 */
2511static void
2512bw_meter_receive_packet(struct bw_meter *x, int plen, struct timeval *nowp)
2513{
2514 struct timeval delta;
2515
2515
2516 MFC_LOCK_ASSERT();
2517
2518 delta = *nowp;
2519 BW_TIMEVALDECR(&delta, &x->bm_start_time);
2516 MFC_LOCK_ASSERT();
2517
2518 delta = *nowp;
2519 BW_TIMEVALDECR(&delta, &x->bm_start_time);
2520
2520
2521 if (x->bm_flags & BW_METER_GEQ) {
2522 /*
2523 * Processing for ">=" type of bw_meter entry
2524 */
2525 if (BW_TIMEVALCMP(&delta, &x->bm_threshold.b_time, >)) {
2526 /* Reset the bw_meter entry */
2527 x->bm_start_time = *nowp;
2528 x->bm_measured.b_packets = 0;
2529 x->bm_measured.b_bytes = 0;
2530 x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
2531 }
2521 if (x->bm_flags & BW_METER_GEQ) {
2522 /*
2523 * Processing for ">=" type of bw_meter entry
2524 */
2525 if (BW_TIMEVALCMP(&delta, &x->bm_threshold.b_time, >)) {
2526 /* Reset the bw_meter entry */
2527 x->bm_start_time = *nowp;
2528 x->bm_measured.b_packets = 0;
2529 x->bm_measured.b_bytes = 0;
2530 x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
2531 }
2532
2532
2533 /* Record that a packet is received */
2534 x->bm_measured.b_packets++;
2535 x->bm_measured.b_bytes += plen;
2533 /* Record that a packet is received */
2534 x->bm_measured.b_packets++;
2535 x->bm_measured.b_bytes += plen;
2536
2536
2537 /*
2538 * Test if we should deliver an upcall
2539 */
2537 /*
2538 * Test if we should deliver an upcall
2539 */
2540 if (!(x->bm_flags & BW_METER_UPCALL_DELIVERED)) {
2540 if (!(x->bm_flags & BW_METER_UPCALL_DELIVERED)) {
2541 if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
2542 (x->bm_measured.b_packets >= x->bm_threshold.b_packets)) ||
2543 ((x->bm_flags & BW_METER_UNIT_BYTES) &&
2544 (x->bm_measured.b_bytes >= x->bm_threshold.b_bytes))) {
2545 /* Prepare an upcall for delivery */
2546 bw_meter_prepare_upcall(x, nowp);
2547 x->bm_flags |= BW_METER_UPCALL_DELIVERED;
2548 }

--- 14 unchanged lines hidden (view full) ---

2563 (x->bm_measured.b_bytes <= x->bm_threshold.b_bytes))) {
2564 /* Prepare an upcall for delivery */
2565 bw_meter_prepare_upcall(x, nowp);
2566 }
2567 /* Reschedule the bw_meter entry */
2568 unschedule_bw_meter(x);
2569 schedule_bw_meter(x, nowp);
2570 }
2541 if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
2542 (x->bm_measured.b_packets >= x->bm_threshold.b_packets)) ||
2543 ((x->bm_flags & BW_METER_UNIT_BYTES) &&
2544 (x->bm_measured.b_bytes >= x->bm_threshold.b_bytes))) {
2545 /* Prepare an upcall for delivery */
2546 bw_meter_prepare_upcall(x, nowp);
2547 x->bm_flags |= BW_METER_UPCALL_DELIVERED;
2548 }

--- 14 unchanged lines hidden (view full) ---

2563 (x->bm_measured.b_bytes <= x->bm_threshold.b_bytes))) {
2564 /* Prepare an upcall for delivery */
2565 bw_meter_prepare_upcall(x, nowp);
2566 }
2567 /* Reschedule the bw_meter entry */
2568 unschedule_bw_meter(x);
2569 schedule_bw_meter(x, nowp);
2570 }
2571
2571
2572 /* Record that a packet is received */
2573 x->bm_measured.b_packets++;
2574 x->bm_measured.b_bytes += plen;
2572 /* Record that a packet is received */
2573 x->bm_measured.b_packets++;
2574 x->bm_measured.b_bytes += plen;
2575
2575
2576 /*
2577 * Test if we should restart the measuring interval
2578 */
2579 if ((x->bm_flags & BW_METER_UNIT_PACKETS &&
2580 x->bm_measured.b_packets <= x->bm_threshold.b_packets) ||
2581 (x->bm_flags & BW_METER_UNIT_BYTES &&
2582 x->bm_measured.b_bytes <= x->bm_threshold.b_bytes)) {
2583 /* Don't restart the measuring interval */

--- 16 unchanged lines hidden (view full) ---

2600/*
2601 * Prepare a bandwidth-related upcall
2602 */
2603static void
2604bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp)
2605{
2606 struct timeval delta;
2607 struct bw_upcall *u;
2576 /*
2577 * Test if we should restart the measuring interval
2578 */
2579 if ((x->bm_flags & BW_METER_UNIT_PACKETS &&
2580 x->bm_measured.b_packets <= x->bm_threshold.b_packets) ||
2581 (x->bm_flags & BW_METER_UNIT_BYTES &&
2582 x->bm_measured.b_bytes <= x->bm_threshold.b_bytes)) {
2583 /* Don't restart the measuring interval */

--- 16 unchanged lines hidden (view full) ---

2600/*
2601 * Prepare a bandwidth-related upcall
2602 */
2603static void
2604bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp)
2605{
2606 struct timeval delta;
2607 struct bw_upcall *u;
2608
2608
2609 MFC_LOCK_ASSERT();
2609 MFC_LOCK_ASSERT();
2610
2610
2611 /*
2611 /*
2612 * Compute the measured time interval
2612 * Compute the measured time interval
2613 */
2614 delta = *nowp;
2615 BW_TIMEVALDECR(&delta, &x->bm_start_time);
2613 */
2614 delta = *nowp;
2615 BW_TIMEVALDECR(&delta, &x->bm_start_time);
2616
2616
2617 /*
2618 * If there are too many pending upcalls, deliver them now
2619 */
2620 if (bw_upcalls_n >= BW_UPCALLS_MAX)
2621 bw_upcalls_send();
2617 /*
2618 * If there are too many pending upcalls, deliver them now
2619 */
2620 if (bw_upcalls_n >= BW_UPCALLS_MAX)
2621 bw_upcalls_send();
2622
2622
2623 /*
2624 * Set the bw_upcall entry
2625 */
2626 u = &bw_upcalls[bw_upcalls_n++];
2627 u->bu_src = x->bm_mfc->mfc_origin;
2628 u->bu_dst = x->bm_mfc->mfc_mcastgrp;
2629 u->bu_threshold.b_time = x->bm_threshold.b_time;
2630 u->bu_threshold.b_packets = x->bm_threshold.b_packets;

--- 24 unchanged lines hidden (view full) ---

2655 static struct igmpmsg igmpmsg = { 0, /* unused1 */
2656 0, /* unused2 */
2657 IGMPMSG_BW_UPCALL,/* im_msgtype */
2658 0, /* im_mbz */
2659 0, /* im_vif */
2660 0, /* unused3 */
2661 { 0 }, /* im_src */
2662 { 0 } }; /* im_dst */
2623 /*
2624 * Set the bw_upcall entry
2625 */
2626 u = &bw_upcalls[bw_upcalls_n++];
2627 u->bu_src = x->bm_mfc->mfc_origin;
2628 u->bu_dst = x->bm_mfc->mfc_mcastgrp;
2629 u->bu_threshold.b_time = x->bm_threshold.b_time;
2630 u->bu_threshold.b_packets = x->bm_threshold.b_packets;

--- 24 unchanged lines hidden (view full) ---

2655 static struct igmpmsg igmpmsg = { 0, /* unused1 */
2656 0, /* unused2 */
2657 IGMPMSG_BW_UPCALL,/* im_msgtype */
2658 0, /* im_mbz */
2659 0, /* im_vif */
2660 0, /* unused3 */
2661 { 0 }, /* im_src */
2662 { 0 } }; /* im_dst */
2663
2663
2664 MFC_LOCK_ASSERT();
2665
2666 if (bw_upcalls_n == 0)
2667 return; /* No pending upcalls */
2668
2669 bw_upcalls_n = 0;
2664 MFC_LOCK_ASSERT();
2665
2666 if (bw_upcalls_n == 0)
2667 return; /* No pending upcalls */
2668
2669 bw_upcalls_n = 0;
2670
2670
2671 /*
2672 * Allocate a new mbuf, initialize it with the header and
2673 * the payload for the pending calls.
2674 */
2675 MGETHDR(m, M_DONTWAIT, MT_HEADER);
2676 if (m == NULL) {
2677 log(LOG_WARNING, "bw_upcalls_send: cannot allocate mbuf\n");
2678 return;
2679 }
2671 /*
2672 * Allocate a new mbuf, initialize it with the header and
2673 * the payload for the pending calls.
2674 */
2675 MGETHDR(m, M_DONTWAIT, MT_HEADER);
2676 if (m == NULL) {
2677 log(LOG_WARNING, "bw_upcalls_send: cannot allocate mbuf\n");
2678 return;
2679 }
2680
2680
2681 m->m_len = m->m_pkthdr.len = 0;
2682 m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg);
2683 m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&bw_upcalls[0]);
2681 m->m_len = m->m_pkthdr.len = 0;
2682 m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg);
2683 m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&bw_upcalls[0]);
2684
2684
2685 /*
2686 * Send the upcalls
2687 * XXX do we need to set the address in k_igmpsrc ?
2688 */
2689 mrtstat.mrts_upcalls++;
2690 if (socket_send(ip_mrouter, m, &k_igmpsrc) < 0) {
2691 log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n");
2692 ++mrtstat.mrts_upq_sockfull;

--- 17 unchanged lines hidden (view full) ---

2710/*
2711 * Schedule a timer to process periodically bw_meter entry of type "<="
2712 * by linking the entry in the proper hash bucket.
2713 */
2714static void
2715schedule_bw_meter(struct bw_meter *x, struct timeval *nowp)
2716{
2717 int time_hash;
2685 /*
2686 * Send the upcalls
2687 * XXX do we need to set the address in k_igmpsrc ?
2688 */
2689 mrtstat.mrts_upcalls++;
2690 if (socket_send(ip_mrouter, m, &k_igmpsrc) < 0) {
2691 log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n");
2692 ++mrtstat.mrts_upq_sockfull;

--- 17 unchanged lines hidden (view full) ---

2710/*
2711 * Schedule a timer to process periodically bw_meter entry of type "<="
2712 * by linking the entry in the proper hash bucket.
2713 */
2714static void
2715schedule_bw_meter(struct bw_meter *x, struct timeval *nowp)
2716{
2717 int time_hash;
2718
2718
2719 MFC_LOCK_ASSERT();
2720
2721 if (!(x->bm_flags & BW_METER_LEQ))
2722 return; /* XXX: we schedule timers only for "<=" entries */
2719 MFC_LOCK_ASSERT();
2720
2721 if (!(x->bm_flags & BW_METER_LEQ))
2722 return; /* XXX: we schedule timers only for "<=" entries */
2723
2723
2724 /*
2725 * Reset the bw_meter entry
2726 */
2727 x->bm_start_time = *nowp;
2728 x->bm_measured.b_packets = 0;
2729 x->bm_measured.b_bytes = 0;
2730 x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
2724 /*
2725 * Reset the bw_meter entry
2726 */
2727 x->bm_start_time = *nowp;
2728 x->bm_measured.b_packets = 0;
2729 x->bm_measured.b_bytes = 0;
2730 x->bm_flags &= ~BW_METER_UPCALL_DELIVERED;
2731
2731
2732 /*
2733 * Compute the timeout hash value and insert the entry
2734 */
2735 BW_METER_TIMEHASH(x, time_hash);
2736 x->bm_time_next = bw_meter_timers[time_hash];
2737 bw_meter_timers[time_hash] = x;
2738 x->bm_time_hash = time_hash;
2739}
2740
2741/*
2742 * Unschedule the periodic timer that processes bw_meter entry of type "<="
2743 * by removing the entry from the proper hash bucket.
2744 */
2745static void
2746unschedule_bw_meter(struct bw_meter *x)
2747{
2748 int time_hash;
2749 struct bw_meter *prev, *tmp;
2732 /*
2733 * Compute the timeout hash value and insert the entry
2734 */
2735 BW_METER_TIMEHASH(x, time_hash);
2736 x->bm_time_next = bw_meter_timers[time_hash];
2737 bw_meter_timers[time_hash] = x;
2738 x->bm_time_hash = time_hash;
2739}
2740
2741/*
2742 * Unschedule the periodic timer that processes bw_meter entry of type "<="
2743 * by removing the entry from the proper hash bucket.
2744 */
2745static void
2746unschedule_bw_meter(struct bw_meter *x)
2747{
2748 int time_hash;
2749 struct bw_meter *prev, *tmp;
2750
2750
2751 MFC_LOCK_ASSERT();
2752
2753 if (!(x->bm_flags & BW_METER_LEQ))
2754 return; /* XXX: we schedule timers only for "<=" entries */
2751 MFC_LOCK_ASSERT();
2752
2753 if (!(x->bm_flags & BW_METER_LEQ))
2754 return; /* XXX: we schedule timers only for "<=" entries */
2755
2755
2756 /*
2757 * Compute the timeout hash value and delete the entry
2758 */
2759 time_hash = x->bm_time_hash;
2760 if (time_hash >= BW_METER_BUCKETS)
2761 return; /* Entry was not scheduled */
2756 /*
2757 * Compute the timeout hash value and delete the entry
2758 */
2759 time_hash = x->bm_time_hash;
2760 if (time_hash >= BW_METER_BUCKETS)
2761 return; /* Entry was not scheduled */
2762
2762
2763 for (prev = NULL, tmp = bw_meter_timers[time_hash];
2764 tmp != NULL; prev = tmp, tmp = tmp->bm_time_next)
2765 if (tmp == x)
2766 break;
2763 for (prev = NULL, tmp = bw_meter_timers[time_hash];
2764 tmp != NULL; prev = tmp, tmp = tmp->bm_time_next)
2765 if (tmp == x)
2766 break;
2767
2767
2768 if (tmp == NULL)
2769 panic("unschedule_bw_meter: bw_meter entry not found");
2768 if (tmp == NULL)
2769 panic("unschedule_bw_meter: bw_meter entry not found");
2770
2770
2771 if (prev != NULL)
2772 prev->bm_time_next = x->bm_time_next;
2773 else
2774 bw_meter_timers[time_hash] = x->bm_time_next;
2771 if (prev != NULL)
2772 prev->bm_time_next = x->bm_time_next;
2773 else
2774 bw_meter_timers[time_hash] = x->bm_time_next;
2775
2775
2776 x->bm_time_next = NULL;
2777 x->bm_time_hash = BW_METER_BUCKETS;
2778}
2779
2780
2781/*
2782 * Process all "<=" type of bw_meter that should be processed now,
2783 * and for each entry prepare an upcall if necessary. Each processed

--- 6 unchanged lines hidden (view full) ---

2790static void
2791bw_meter_process()
2792{
2793 static uint32_t last_tv_sec; /* last time we processed this */
2794
2795 uint32_t loops;
2796 int i;
2797 struct timeval now, process_endtime;
2776 x->bm_time_next = NULL;
2777 x->bm_time_hash = BW_METER_BUCKETS;
2778}
2779
2780
2781/*
2782 * Process all "<=" type of bw_meter that should be processed now,
2783 * and for each entry prepare an upcall if necessary. Each processed

--- 6 unchanged lines hidden (view full) ---

2790static void
2791bw_meter_process()
2792{
2793 static uint32_t last_tv_sec; /* last time we processed this */
2794
2795 uint32_t loops;
2796 int i;
2797 struct timeval now, process_endtime;
2798
2798
2799 GET_TIME(now);
2800 if (last_tv_sec == now.tv_sec)
2801 return; /* nothing to do */
2802
2803 loops = now.tv_sec - last_tv_sec;
2804 last_tv_sec = now.tv_sec;
2805 if (loops > BW_METER_BUCKETS)
2806 loops = BW_METER_BUCKETS;
2807
2808 MFC_LOCK();
2809 /*
2810 * Process all bins of bw_meter entries from the one after the last
2811 * processed to the current one. On entry, i points to the last bucket
2812 * visited, so we need to increment i at the beginning of the loop.
2813 */
2814 for (i = (now.tv_sec - loops) % BW_METER_BUCKETS; loops > 0; loops--) {
2815 struct bw_meter *x, *tmp_list;
2799 GET_TIME(now);
2800 if (last_tv_sec == now.tv_sec)
2801 return; /* nothing to do */
2802
2803 loops = now.tv_sec - last_tv_sec;
2804 last_tv_sec = now.tv_sec;
2805 if (loops > BW_METER_BUCKETS)
2806 loops = BW_METER_BUCKETS;
2807
2808 MFC_LOCK();
2809 /*
2810 * Process all bins of bw_meter entries from the one after the last
2811 * processed to the current one. On entry, i points to the last bucket
2812 * visited, so we need to increment i at the beginning of the loop.
2813 */
2814 for (i = (now.tv_sec - loops) % BW_METER_BUCKETS; loops > 0; loops--) {
2815 struct bw_meter *x, *tmp_list;
2816
2816
2817 if (++i >= BW_METER_BUCKETS)
2818 i = 0;
2817 if (++i >= BW_METER_BUCKETS)
2818 i = 0;
2819
2819
2820 /* Disconnect the list of bw_meter entries from the bin */
2821 tmp_list = bw_meter_timers[i];
2822 bw_meter_timers[i] = NULL;
2820 /* Disconnect the list of bw_meter entries from the bin */
2821 tmp_list = bw_meter_timers[i];
2822 bw_meter_timers[i] = NULL;
2823
2823
2824 /* Process the list of bw_meter entries */
2825 while (tmp_list != NULL) {
2826 x = tmp_list;
2827 tmp_list = tmp_list->bm_time_next;
2824 /* Process the list of bw_meter entries */
2825 while (tmp_list != NULL) {
2826 x = tmp_list;
2827 tmp_list = tmp_list->bm_time_next;
2828
2828
2829 /* Test if the time interval is over */
2830 process_endtime = x->bm_start_time;
2831 BW_TIMEVALADD(&process_endtime, &x->bm_threshold.b_time);
2832 if (BW_TIMEVALCMP(&process_endtime, &now, >)) {
2833 /* Not yet: reschedule, but don't reset */
2834 int time_hash;
2829 /* Test if the time interval is over */
2830 process_endtime = x->bm_start_time;
2831 BW_TIMEVALADD(&process_endtime, &x->bm_threshold.b_time);
2832 if (BW_TIMEVALCMP(&process_endtime, &now, >)) {
2833 /* Not yet: reschedule, but don't reset */
2834 int time_hash;
2835
2835
2836 BW_METER_TIMEHASH(x, time_hash);
2837 if (time_hash == i && process_endtime.tv_sec == now.tv_sec) {
2838 /*
2839 * XXX: somehow the bin processing is a bit ahead of time.
2840 * Put the entry in the next bin.
2841 */
2842 if (++time_hash >= BW_METER_BUCKETS)
2843 time_hash = 0;
2844 }
2845 x->bm_time_next = bw_meter_timers[time_hash];
2846 bw_meter_timers[time_hash] = x;
2847 x->bm_time_hash = time_hash;
2836 BW_METER_TIMEHASH(x, time_hash);
2837 if (time_hash == i && process_endtime.tv_sec == now.tv_sec) {
2838 /*
2839 * XXX: somehow the bin processing is a bit ahead of time.
2840 * Put the entry in the next bin.
2841 */
2842 if (++time_hash >= BW_METER_BUCKETS)
2843 time_hash = 0;
2844 }
2845 x->bm_time_next = bw_meter_timers[time_hash];
2846 bw_meter_timers[time_hash] = x;
2847 x->bm_time_hash = time_hash;
2848
2848
2849 continue;
2850 }
2849 continue;
2850 }
2851
2851
2852 /*
2853 * Test if we should deliver an upcall
2854 */
2855 if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
2856 (x->bm_measured.b_packets <= x->bm_threshold.b_packets)) ||
2857 ((x->bm_flags & BW_METER_UNIT_BYTES) &&
2858 (x->bm_measured.b_bytes <= x->bm_threshold.b_bytes))) {
2859 /* Prepare an upcall for delivery */
2860 bw_meter_prepare_upcall(x, &now);
2861 }
2852 /*
2853 * Test if we should deliver an upcall
2854 */
2855 if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
2856 (x->bm_measured.b_packets <= x->bm_threshold.b_packets)) ||
2857 ((x->bm_flags & BW_METER_UNIT_BYTES) &&
2858 (x->bm_measured.b_bytes <= x->bm_threshold.b_bytes))) {
2859 /* Prepare an upcall for delivery */
2860 bw_meter_prepare_upcall(x, &now);
2861 }
2862
2862
2863 /*
2864 * Reschedule for next processing
2865 */
2866 schedule_bw_meter(x, &now);
2867 }
2868 }
2863 /*
2864 * Reschedule for next processing
2865 */
2866 schedule_bw_meter(x, &now);
2867 }
2868 }
2869
2869
2870 /* Send all upcalls that are pending delivery */
2871 bw_upcalls_send();
2872
2873 MFC_UNLOCK();
2874}
2875
2876/*
2877 * A periodic function for sending all upcalls that are pending delivery
2878 */
2879static void
2880expire_bw_upcalls_send(void *unused)
2881{
2882 MFC_LOCK();
2883 bw_upcalls_send();
2884 MFC_UNLOCK();
2870 /* Send all upcalls that are pending delivery */
2871 bw_upcalls_send();
2872
2873 MFC_UNLOCK();
2874}
2875
2876/*
2877 * A periodic function for sending all upcalls that are pending delivery
2878 */
2879static void
2880expire_bw_upcalls_send(void *unused)
2881{
2882 MFC_LOCK();
2883 bw_upcalls_send();
2884 MFC_UNLOCK();
2885
2885
2886 callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD,
2887 expire_bw_upcalls_send, NULL);
2888}
2889
2890/*
2891 * A periodic function for periodic scanning of the multicast forwarding
2892 * table for processing all "<=" bw_meter entries.
2893 */
2894static void
2895expire_bw_meter_process(void *unused)
2896{
2897 if (mrt_api_config & MRT_MFC_BW_UPCALL)
2898 bw_meter_process();
2886 callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD,
2887 expire_bw_upcalls_send, NULL);
2888}
2889
2890/*
2891 * A periodic function for periodic scanning of the multicast forwarding
2892 * table for processing all "<=" bw_meter entries.
2893 */
2894static void
2895expire_bw_meter_process(void *unused)
2896{
2897 if (mrt_api_config & MRT_MFC_BW_UPCALL)
2898 bw_meter_process();
2899
2899
2900 callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL);
2901}
2902
2903/*
2904 * End of bandwidth monitoring code
2905 */
2906
2907#ifdef PIM
2908/*
2909 * Send the packet up to the user daemon, or eventually do kernel encapsulation
2910 *
2911 */
2912static int
2913pim_register_send(struct ip *ip, struct vif *vifp,
2914 struct mbuf *m, struct mfc *rt)
2915{
2916 struct mbuf *mb_copy, *mm;
2900 callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL);
2901}
2902
2903/*
2904 * End of bandwidth monitoring code
2905 */
2906
2907#ifdef PIM
2908/*
2909 * Send the packet up to the user daemon, or eventually do kernel encapsulation
2910 *
2911 */
2912static int
2913pim_register_send(struct ip *ip, struct vif *vifp,
2914 struct mbuf *m, struct mfc *rt)
2915{
2916 struct mbuf *mb_copy, *mm;
2917
2917
2918 if (mrtdebug & DEBUG_PIM)
2918 if (mrtdebug & DEBUG_PIM)
2919 log(LOG_DEBUG, "pim_register_send: ");
2920
2919 log(LOG_DEBUG, "pim_register_send: ");
2920
2921 mb_copy = pim_register_prepare(ip, m);
2922 if (mb_copy == NULL)
2923 return ENOBUFS;
2921 mb_copy = pim_register_prepare(ip, m);
2922 if (mb_copy == NULL)
2923 return ENOBUFS;
2924
2924
2925 /*
2926 * Send all the fragments. Note that the mbuf for each fragment
2927 * is freed by the sending machinery.
2928 */
2929 for (mm = mb_copy; mm; mm = mb_copy) {
2930 mb_copy = mm->m_nextpkt;
2931 mm->m_nextpkt = 0;
2932 mm = m_pullup(mm, sizeof(struct ip));
2933 if (mm != NULL) {
2934 ip = mtod(mm, struct ip *);
2935 if ((mrt_api_config & MRT_MFC_RP) &&
2936 (rt->mfc_rp.s_addr != INADDR_ANY)) {
2937 pim_register_send_rp(ip, vifp, mm, rt);
2938 } else {
2939 pim_register_send_upcall(ip, vifp, mm, rt);
2940 }
2941 }
2942 }
2925 /*
2926 * Send all the fragments. Note that the mbuf for each fragment
2927 * is freed by the sending machinery.
2928 */
2929 for (mm = mb_copy; mm; mm = mb_copy) {
2930 mb_copy = mm->m_nextpkt;
2931 mm->m_nextpkt = 0;
2932 mm = m_pullup(mm, sizeof(struct ip));
2933 if (mm != NULL) {
2934 ip = mtod(mm, struct ip *);
2935 if ((mrt_api_config & MRT_MFC_RP) &&
2936 (rt->mfc_rp.s_addr != INADDR_ANY)) {
2937 pim_register_send_rp(ip, vifp, mm, rt);
2938 } else {
2939 pim_register_send_upcall(ip, vifp, mm, rt);
2940 }
2941 }
2942 }
2943
2943
2944 return 0;
2945}
2946
2947/*
2948 * Return a copy of the data packet that is ready for PIM Register
2949 * encapsulation.
2950 * XXX: Note that in the returned copy the IP header is a valid one.
2951 */
2952static struct mbuf *
2953pim_register_prepare(struct ip *ip, struct mbuf *m)
2954{
2955 struct mbuf *mb_copy = NULL;
2956 int mtu;
2944 return 0;
2945}
2946
2947/*
2948 * Return a copy of the data packet that is ready for PIM Register
2949 * encapsulation.
2950 * XXX: Note that in the returned copy the IP header is a valid one.
2951 */
2952static struct mbuf *
2953pim_register_prepare(struct ip *ip, struct mbuf *m)
2954{
2955 struct mbuf *mb_copy = NULL;
2956 int mtu;
2957
2957
2958 /* Take care of delayed checksums */
2959 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
2960 in_delayed_cksum(m);
2961 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
2962 }
2963
2964 /*
2965 * Copy the old packet & pullup its IP header into the
2966 * new mbuf so we can modify it.
2967 */
2968 mb_copy = m_copypacket(m, M_DONTWAIT);
2969 if (mb_copy == NULL)
2970 return NULL;
2971 mb_copy = m_pullup(mb_copy, ip->ip_hl << 2);
2972 if (mb_copy == NULL)
2973 return NULL;
2958 /* Take care of delayed checksums */
2959 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
2960 in_delayed_cksum(m);
2961 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
2962 }
2963
2964 /*
2965 * Copy the old packet & pullup its IP header into the
2966 * new mbuf so we can modify it.
2967 */
2968 mb_copy = m_copypacket(m, M_DONTWAIT);
2969 if (mb_copy == NULL)
2970 return NULL;
2971 mb_copy = m_pullup(mb_copy, ip->ip_hl << 2);
2972 if (mb_copy == NULL)
2973 return NULL;
2974
2974
2975 /* take care of the TTL */
2976 ip = mtod(mb_copy, struct ip *);
2977 --ip->ip_ttl;
2975 /* take care of the TTL */
2976 ip = mtod(mb_copy, struct ip *);
2977 --ip->ip_ttl;
2978
2978
2979 /* Compute the MTU after the PIM Register encapsulation */
2980 mtu = 0xffff - sizeof(pim_encap_iphdr) - sizeof(pim_encap_pimhdr);
2979 /* Compute the MTU after the PIM Register encapsulation */
2980 mtu = 0xffff - sizeof(pim_encap_iphdr) - sizeof(pim_encap_pimhdr);
2981
2981
2982 if (ip->ip_len <= mtu) {
2983 /* Turn the IP header into a valid one */
2984 ip->ip_len = htons(ip->ip_len);
2985 ip->ip_off = htons(ip->ip_off);
2986 ip->ip_sum = 0;
2987 ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
2988 } else {
2989 /* Fragment the packet */

--- 11 unchanged lines hidden (view full) ---

3001static int
3002pim_register_send_upcall(struct ip *ip, struct vif *vifp,
3003 struct mbuf *mb_copy, struct mfc *rt)
3004{
3005 struct mbuf *mb_first;
3006 int len = ntohs(ip->ip_len);
3007 struct igmpmsg *im;
3008 struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
2982 if (ip->ip_len <= mtu) {
2983 /* Turn the IP header into a valid one */
2984 ip->ip_len = htons(ip->ip_len);
2985 ip->ip_off = htons(ip->ip_off);
2986 ip->ip_sum = 0;
2987 ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
2988 } else {
2989 /* Fragment the packet */

--- 11 unchanged lines hidden (view full) ---

3001static int
3002pim_register_send_upcall(struct ip *ip, struct vif *vifp,
3003 struct mbuf *mb_copy, struct mfc *rt)
3004{
3005 struct mbuf *mb_first;
3006 int len = ntohs(ip->ip_len);
3007 struct igmpmsg *im;
3008 struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
3009
3009
3010 VIF_LOCK_ASSERT();
3011
3012 /*
3013 * Add a new mbuf with an upcall header
3014 */
3015 MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
3016 if (mb_first == NULL) {
3017 m_freem(mb_copy);
3018 return ENOBUFS;
3019 }
3020 mb_first->m_data += max_linkhdr;
3021 mb_first->m_pkthdr.len = len + sizeof(struct igmpmsg);
3022 mb_first->m_len = sizeof(struct igmpmsg);
3023 mb_first->m_next = mb_copy;
3010 VIF_LOCK_ASSERT();
3011
3012 /*
3013 * Add a new mbuf with an upcall header
3014 */
3015 MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
3016 if (mb_first == NULL) {
3017 m_freem(mb_copy);
3018 return ENOBUFS;
3019 }
3020 mb_first->m_data += max_linkhdr;
3021 mb_first->m_pkthdr.len = len + sizeof(struct igmpmsg);
3022 mb_first->m_len = sizeof(struct igmpmsg);
3023 mb_first->m_next = mb_copy;
3024
3024
3025 /* Send message to routing daemon */
3026 im = mtod(mb_first, struct igmpmsg *);
3027 im->im_msgtype = IGMPMSG_WHOLEPKT;
3028 im->im_mbz = 0;
3029 im->im_vif = vifp - viftable;
3030 im->im_src = ip->ip_src;
3031 im->im_dst = ip->ip_dst;
3025 /* Send message to routing daemon */
3026 im = mtod(mb_first, struct igmpmsg *);
3027 im->im_msgtype = IGMPMSG_WHOLEPKT;
3028 im->im_mbz = 0;
3029 im->im_vif = vifp - viftable;
3030 im->im_src = ip->ip_src;
3031 im->im_dst = ip->ip_dst;
3032
3032
3033 k_igmpsrc.sin_addr = ip->ip_src;
3033 k_igmpsrc.sin_addr = ip->ip_src;
3034
3034
3035 mrtstat.mrts_upcalls++;
3035 mrtstat.mrts_upcalls++;
3036
3036
3037 if (socket_send(ip_mrouter, mb_first, &k_igmpsrc) < 0) {
3038 if (mrtdebug & DEBUG_PIM)
3039 log(LOG_WARNING,
3040 "mcast: pim_register_send_upcall: ip_mrouter socket queue full");
3041 ++mrtstat.mrts_upq_sockfull;
3042 return ENOBUFS;
3043 }
3037 if (socket_send(ip_mrouter, mb_first, &k_igmpsrc) < 0) {
3038 if (mrtdebug & DEBUG_PIM)
3039 log(LOG_WARNING,
3040 "mcast: pim_register_send_upcall: ip_mrouter socket queue full");
3041 ++mrtstat.mrts_upq_sockfull;
3042 return ENOBUFS;
3043 }
3044
3044
3045 /* Keep statistics */
3046 pimstat.pims_snd_registers_msgs++;
3047 pimstat.pims_snd_registers_bytes += len;
3045 /* Keep statistics */
3046 pimstat.pims_snd_registers_msgs++;
3047 pimstat.pims_snd_registers_bytes += len;
3048
3048
3049 return 0;
3050}
3051
3052/*
3053 * Encapsulate the data packet in PIM Register message and send it to the RP.
3054 */
3055static int
3056pim_register_send_rp(struct ip *ip, struct vif *vifp,
3057 struct mbuf *mb_copy, struct mfc *rt)
3058{
3059 struct mbuf *mb_first;
3060 struct ip *ip_outer;
3061 struct pim_encap_pimhdr *pimhdr;
3062 int len = ntohs(ip->ip_len);
3063 vifi_t vifi = rt->mfc_parent;
3049 return 0;
3050}
3051
3052/*
3053 * Encapsulate the data packet in PIM Register message and send it to the RP.
3054 */
3055static int
3056pim_register_send_rp(struct ip *ip, struct vif *vifp,
3057 struct mbuf *mb_copy, struct mfc *rt)
3058{
3059 struct mbuf *mb_first;
3060 struct ip *ip_outer;
3061 struct pim_encap_pimhdr *pimhdr;
3062 int len = ntohs(ip->ip_len);
3063 vifi_t vifi = rt->mfc_parent;
3064
3064
3065 VIF_LOCK_ASSERT();
3065 VIF_LOCK_ASSERT();
3066
3066
3067 if ((vifi >= numvifs) || (viftable[vifi].v_lcl_addr.s_addr == 0)) {
3068 m_freem(mb_copy);
3069 return EADDRNOTAVAIL; /* The iif vif is invalid */
3070 }
3067 if ((vifi >= numvifs) || (viftable[vifi].v_lcl_addr.s_addr == 0)) {
3068 m_freem(mb_copy);
3069 return EADDRNOTAVAIL; /* The iif vif is invalid */
3070 }
3071
3071
3072 /*
3073 * Add a new mbuf with the encapsulating header
3074 */
3075 MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
3076 if (mb_first == NULL) {
3077 m_freem(mb_copy);
3078 return ENOBUFS;
3079 }
3080 mb_first->m_data += max_linkhdr;
3081 mb_first->m_len = sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
3082 mb_first->m_next = mb_copy;
3083
3084 mb_first->m_pkthdr.len = len + mb_first->m_len;
3072 /*
3073 * Add a new mbuf with the encapsulating header
3074 */
3075 MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
3076 if (mb_first == NULL) {
3077 m_freem(mb_copy);
3078 return ENOBUFS;
3079 }
3080 mb_first->m_data += max_linkhdr;
3081 mb_first->m_len = sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
3082 mb_first->m_next = mb_copy;
3083
3084 mb_first->m_pkthdr.len = len + mb_first->m_len;
3085
3085
3086 /*
3087 * Fill in the encapsulating IP and PIM header
3088 */
3089 ip_outer = mtod(mb_first, struct ip *);
3090 *ip_outer = pim_encap_iphdr;
3091 ip_outer->ip_id = ip_newid();
3092 ip_outer->ip_len = len + sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
3093 ip_outer->ip_src = viftable[vifi].v_lcl_addr;

--- 6 unchanged lines hidden (view full) ---

3100 if (ntohs(ip->ip_off) & IP_DF)
3101 ip_outer->ip_off |= IP_DF;
3102 pimhdr = (struct pim_encap_pimhdr *)((caddr_t)ip_outer
3103 + sizeof(pim_encap_iphdr));
3104 *pimhdr = pim_encap_pimhdr;
3105 /* If the iif crosses a border, set the Border-bit */
3106 if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mrt_api_config)
3107 pimhdr->flags |= htonl(PIM_BORDER_REGISTER);
3086 /*
3087 * Fill in the encapsulating IP and PIM header
3088 */
3089 ip_outer = mtod(mb_first, struct ip *);
3090 *ip_outer = pim_encap_iphdr;
3091 ip_outer->ip_id = ip_newid();
3092 ip_outer->ip_len = len + sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
3093 ip_outer->ip_src = viftable[vifi].v_lcl_addr;

--- 6 unchanged lines hidden (view full) ---

3100 if (ntohs(ip->ip_off) & IP_DF)
3101 ip_outer->ip_off |= IP_DF;
3102 pimhdr = (struct pim_encap_pimhdr *)((caddr_t)ip_outer
3103 + sizeof(pim_encap_iphdr));
3104 *pimhdr = pim_encap_pimhdr;
3105 /* If the iif crosses a border, set the Border-bit */
3106 if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mrt_api_config)
3107 pimhdr->flags |= htonl(PIM_BORDER_REGISTER);
3108
3108
3109 mb_first->m_data += sizeof(pim_encap_iphdr);
3110 pimhdr->pim.pim_cksum = in_cksum(mb_first, sizeof(pim_encap_pimhdr));
3111 mb_first->m_data -= sizeof(pim_encap_iphdr);
3109 mb_first->m_data += sizeof(pim_encap_iphdr);
3110 pimhdr->pim.pim_cksum = in_cksum(mb_first, sizeof(pim_encap_pimhdr));
3111 mb_first->m_data -= sizeof(pim_encap_iphdr);
3112
3112
3113 if (vifp->v_rate_limit == 0)
3114 tbf_send_packet(vifp, mb_first);
3115 else
3116 tbf_control(vifp, mb_first, ip, ip_outer->ip_len);
3113 if (vifp->v_rate_limit == 0)
3114 tbf_send_packet(vifp, mb_first);
3115 else
3116 tbf_control(vifp, mb_first, ip, ip_outer->ip_len);
3117
3117
3118 /* Keep statistics */
3119 pimstat.pims_snd_registers_msgs++;
3120 pimstat.pims_snd_registers_bytes += len;
3118 /* Keep statistics */
3119 pimstat.pims_snd_registers_msgs++;
3120 pimstat.pims_snd_registers_bytes += len;
3121
3121
3122 return 0;
3123}
3124
3125/*
3126 * PIM-SMv2 and PIM-DM messages processing.
3127 * Receives and verifies the PIM control messages, and passes them
3128 * up to the listening socket, using rip_input().
3129 * The only message with special processing is the PIM_REGISTER message

--- 4 unchanged lines hidden (view full) ---

3134pim_input(struct mbuf *m, int off)
3135{
3136 struct ip *ip = mtod(m, struct ip *);
3137 struct pim *pim;
3138 int minlen;
3139 int datalen = ip->ip_len;
3140 int ip_tos;
3141 int iphlen = off;
3122 return 0;
3123}
3124
3125/*
3126 * PIM-SMv2 and PIM-DM messages processing.
3127 * Receives and verifies the PIM control messages, and passes them
3128 * up to the listening socket, using rip_input().
3129 * The only message with special processing is the PIM_REGISTER message

--- 4 unchanged lines hidden (view full) ---

3134pim_input(struct mbuf *m, int off)
3135{
3136 struct ip *ip = mtod(m, struct ip *);
3137 struct pim *pim;
3138 int minlen;
3139 int datalen = ip->ip_len;
3140 int ip_tos;
3141 int iphlen = off;
3142
3142
3143 /* Keep statistics */
3144 pimstat.pims_rcv_total_msgs++;
3145 pimstat.pims_rcv_total_bytes += datalen;
3143 /* Keep statistics */
3144 pimstat.pims_rcv_total_msgs++;
3145 pimstat.pims_rcv_total_bytes += datalen;
3146
3146
3147 /*
3148 * Validate lengths
3149 */
3150 if (datalen < PIM_MINLEN) {
3151 pimstat.pims_rcv_tooshort++;
3152 log(LOG_ERR, "pim_input: packet size too small %d from %lx\n",
3153 datalen, (u_long)ip->ip_src.s_addr);
3154 m_freem(m);
3155 return;
3156 }
3147 /*
3148 * Validate lengths
3149 */
3150 if (datalen < PIM_MINLEN) {
3151 pimstat.pims_rcv_tooshort++;
3152 log(LOG_ERR, "pim_input: packet size too small %d from %lx\n",
3153 datalen, (u_long)ip->ip_src.s_addr);
3154 m_freem(m);
3155 return;
3156 }
3157
3157
3158 /*
3159 * If the packet is at least as big as a REGISTER, go agead
3160 * and grab the PIM REGISTER header size, to avoid another
3161 * possible m_pullup() later.
3158 /*
3159 * If the packet is at least as big as a REGISTER, go agead
3160 * and grab the PIM REGISTER header size, to avoid another
3161 * possible m_pullup() later.
3162 *
3162 *
3163 * PIM_MINLEN == pimhdr + u_int32_t == 4 + 4 = 8
3164 * PIM_REG_MINLEN == pimhdr + reghdr + encap_iphdr == 4 + 4 + 20 = 28
3165 */
3166 minlen = iphlen + (datalen >= PIM_REG_MINLEN ? PIM_REG_MINLEN : PIM_MINLEN);
3167 /*
3168 * Get the IP and PIM headers in contiguous memory, and
3169 * possibly the PIM REGISTER header.
3170 */
3171 if ((m->m_flags & M_EXT || m->m_len < minlen) &&
3172 (m = m_pullup(m, minlen)) == 0) {
3173 log(LOG_ERR, "pim_input: m_pullup failure\n");
3174 return;
3175 }
3176 /* m_pullup() may have given us a new mbuf so reset ip. */
3177 ip = mtod(m, struct ip *);
3178 ip_tos = ip->ip_tos;
3163 * PIM_MINLEN == pimhdr + u_int32_t == 4 + 4 = 8
3164 * PIM_REG_MINLEN == pimhdr + reghdr + encap_iphdr == 4 + 4 + 20 = 28
3165 */
3166 minlen = iphlen + (datalen >= PIM_REG_MINLEN ? PIM_REG_MINLEN : PIM_MINLEN);
3167 /*
3168 * Get the IP and PIM headers in contiguous memory, and
3169 * possibly the PIM REGISTER header.
3170 */
3171 if ((m->m_flags & M_EXT || m->m_len < minlen) &&
3172 (m = m_pullup(m, minlen)) == 0) {
3173 log(LOG_ERR, "pim_input: m_pullup failure\n");
3174 return;
3175 }
3176 /* m_pullup() may have given us a new mbuf so reset ip. */
3177 ip = mtod(m, struct ip *);
3178 ip_tos = ip->ip_tos;
3179
3179
3180 /* adjust mbuf to point to the PIM header */
3181 m->m_data += iphlen;
3182 m->m_len -= iphlen;
3183 pim = mtod(m, struct pim *);
3180 /* adjust mbuf to point to the PIM header */
3181 m->m_data += iphlen;
3182 m->m_len -= iphlen;
3183 pim = mtod(m, struct pim *);
3184
3184
3185 /*
3186 * Validate checksum. If PIM REGISTER, exclude the data packet.
3187 *
3188 * XXX: some older PIMv2 implementations don't make this distinction,
3189 * so for compatibility reason perform the checksum over part of the
3190 * message, and if error, then over the whole message.
3191 */
3192 if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) {

--- 9 unchanged lines hidden (view full) ---

3202 /* PIM version check */
3203 if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) {
3204 pimstat.pims_rcv_badversion++;
3205 log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n",
3206 PIM_VT_V(pim->pim_vt), PIM_VERSION);
3207 m_freem(m);
3208 return;
3209 }
3185 /*
3186 * Validate checksum. If PIM REGISTER, exclude the data packet.
3187 *
3188 * XXX: some older PIMv2 implementations don't make this distinction,
3189 * so for compatibility reason perform the checksum over part of the
3190 * message, and if error, then over the whole message.
3191 */
3192 if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) {

--- 9 unchanged lines hidden (view full) ---

3202 /* PIM version check */
3203 if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) {
3204 pimstat.pims_rcv_badversion++;
3205 log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n",
3206 PIM_VT_V(pim->pim_vt), PIM_VERSION);
3207 m_freem(m);
3208 return;
3209 }
3210
3210
3211 /* restore mbuf back to the outer IP */
3212 m->m_data -= iphlen;
3213 m->m_len += iphlen;
3211 /* restore mbuf back to the outer IP */
3212 m->m_data -= iphlen;
3213 m->m_len += iphlen;
3214
3214
3215 if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER) {
3216 /*
3217 * Since this is a REGISTER, we'll make a copy of the register
3218 * headers ip + pim + u_int32 + encap_ip, to be passed up to the
3219 * routing daemon.
3220 */
3221 struct sockaddr_in dst = { sizeof(dst), AF_INET };
3222 struct mbuf *mcp;
3223 struct ip *encap_ip;
3224 u_int32_t *reghdr;
3225 struct ifnet *vifp;
3215 if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER) {
3216 /*
3217 * Since this is a REGISTER, we'll make a copy of the register
3218 * headers ip + pim + u_int32 + encap_ip, to be passed up to the
3219 * routing daemon.
3220 */
3221 struct sockaddr_in dst = { sizeof(dst), AF_INET };
3222 struct mbuf *mcp;
3223 struct ip *encap_ip;
3224 u_int32_t *reghdr;
3225 struct ifnet *vifp;
3226
3226
3227 VIF_LOCK();
3228 if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) {
3229 VIF_UNLOCK();
3230 if (mrtdebug & DEBUG_PIM)
3231 log(LOG_DEBUG,
3232 "pim_input: register vif not set: %d\n", reg_vif_num);
3233 m_freem(m);
3234 return;
3235 }
3236 /* XXX need refcnt? */
3237 vifp = viftable[reg_vif_num].v_ifp;
3238 VIF_UNLOCK();
3227 VIF_LOCK();
3228 if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) {
3229 VIF_UNLOCK();
3230 if (mrtdebug & DEBUG_PIM)
3231 log(LOG_DEBUG,
3232 "pim_input: register vif not set: %d\n", reg_vif_num);
3233 m_freem(m);
3234 return;
3235 }
3236 /* XXX need refcnt? */
3237 vifp = viftable[reg_vif_num].v_ifp;
3238 VIF_UNLOCK();
3239
3239
3240 /*
3241 * Validate length
3242 */
3243 if (datalen < PIM_REG_MINLEN) {
3244 pimstat.pims_rcv_tooshort++;
3245 pimstat.pims_rcv_badregisters++;
3246 log(LOG_ERR,
3247 "pim_input: register packet size too small %d from %lx\n",
3248 datalen, (u_long)ip->ip_src.s_addr);
3249 m_freem(m);
3250 return;
3251 }
3240 /*
3241 * Validate length
3242 */
3243 if (datalen < PIM_REG_MINLEN) {
3244 pimstat.pims_rcv_tooshort++;
3245 pimstat.pims_rcv_badregisters++;
3246 log(LOG_ERR,
3247 "pim_input: register packet size too small %d from %lx\n",
3248 datalen, (u_long)ip->ip_src.s_addr);
3249 m_freem(m);
3250 return;
3251 }
3252
3252
3253 reghdr = (u_int32_t *)(pim + 1);
3254 encap_ip = (struct ip *)(reghdr + 1);
3253 reghdr = (u_int32_t *)(pim + 1);
3254 encap_ip = (struct ip *)(reghdr + 1);
3255
3255
3256 if (mrtdebug & DEBUG_PIM) {
3257 log(LOG_DEBUG,
3258 "pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n",
3259 (u_long)ntohl(encap_ip->ip_src.s_addr),
3260 (u_long)ntohl(encap_ip->ip_dst.s_addr),
3261 ntohs(encap_ip->ip_len));
3262 }
3256 if (mrtdebug & DEBUG_PIM) {
3257 log(LOG_DEBUG,
3258 "pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n",
3259 (u_long)ntohl(encap_ip->ip_src.s_addr),
3260 (u_long)ntohl(encap_ip->ip_dst.s_addr),
3261 ntohs(encap_ip->ip_len));
3262 }
3263
3263
3264 /* verify the version number of the inner packet */
3265 if (encap_ip->ip_v != IPVERSION) {
3266 pimstat.pims_rcv_badregisters++;
3267 if (mrtdebug & DEBUG_PIM) {
3268 log(LOG_DEBUG, "pim_input: invalid IP version (%d) "
3269 "of the inner packet\n", encap_ip->ip_v);
3270 }
3271 m_freem(m);
3272 return;
3273 }
3264 /* verify the version number of the inner packet */
3265 if (encap_ip->ip_v != IPVERSION) {
3266 pimstat.pims_rcv_badregisters++;
3267 if (mrtdebug & DEBUG_PIM) {
3268 log(LOG_DEBUG, "pim_input: invalid IP version (%d) "
3269 "of the inner packet\n", encap_ip->ip_v);
3270 }
3271 m_freem(m);
3272 return;
3273 }
3274
3274
3275 /* verify the inner packet is destined to a mcast group */
3276 if (!IN_MULTICAST(ntohl(encap_ip->ip_dst.s_addr))) {
3277 pimstat.pims_rcv_badregisters++;
3278 if (mrtdebug & DEBUG_PIM)
3279 log(LOG_DEBUG,
3280 "pim_input: inner packet of register is not "
3281 "multicast %lx\n",
3282 (u_long)ntohl(encap_ip->ip_dst.s_addr));

--- 7 unchanged lines hidden (view full) ---

3290
3291 /*
3292 * Copy the TOS from the outer IP header to the inner IP header.
3293 */
3294 if (encap_ip->ip_tos != ip_tos) {
3295 /* Outer TOS -> inner TOS */
3296 encap_ip->ip_tos = ip_tos;
3297 /* Recompute the inner header checksum. Sigh... */
3275 /* verify the inner packet is destined to a mcast group */
3276 if (!IN_MULTICAST(ntohl(encap_ip->ip_dst.s_addr))) {
3277 pimstat.pims_rcv_badregisters++;
3278 if (mrtdebug & DEBUG_PIM)
3279 log(LOG_DEBUG,
3280 "pim_input: inner packet of register is not "
3281 "multicast %lx\n",
3282 (u_long)ntohl(encap_ip->ip_dst.s_addr));

--- 7 unchanged lines hidden (view full) ---

3290
3291 /*
3292 * Copy the TOS from the outer IP header to the inner IP header.
3293 */
3294 if (encap_ip->ip_tos != ip_tos) {
3295 /* Outer TOS -> inner TOS */
3296 encap_ip->ip_tos = ip_tos;
3297 /* Recompute the inner header checksum. Sigh... */
3298
3298
3299 /* adjust mbuf to point to the inner IP header */
3300 m->m_data += (iphlen + PIM_MINLEN);
3301 m->m_len -= (iphlen + PIM_MINLEN);
3299 /* adjust mbuf to point to the inner IP header */
3300 m->m_data += (iphlen + PIM_MINLEN);
3301 m->m_len -= (iphlen + PIM_MINLEN);
3302
3302
3303 encap_ip->ip_sum = 0;
3304 encap_ip->ip_sum = in_cksum(m, encap_ip->ip_hl << 2);
3303 encap_ip->ip_sum = 0;
3304 encap_ip->ip_sum = in_cksum(m, encap_ip->ip_hl << 2);
3305
3305
3306 /* restore mbuf to point back to the outer IP header */
3307 m->m_data -= (iphlen + PIM_MINLEN);
3308 m->m_len += (iphlen + PIM_MINLEN);
3309 }
3310
3311 /*
3312 * Decapsulate the inner IP packet and loopback to forward it
3306 /* restore mbuf to point back to the outer IP header */
3307 m->m_data -= (iphlen + PIM_MINLEN);
3308 m->m_len += (iphlen + PIM_MINLEN);
3309 }
3310
3311 /*
3312 * Decapsulate the inner IP packet and loopback to forward it
3313 * as a normal multicast packet. Also, make a copy of the
3313 * as a normal multicast packet. Also, make a copy of the
3314 * outer_iphdr + pimhdr + reghdr + encap_iphdr
3315 * to pass to the daemon later, so it can take the appropriate
3316 * actions (e.g., send back PIM_REGISTER_STOP).
3317 * XXX: here m->m_data points to the outer IP header.
3318 */
3319 mcp = m_copy(m, 0, iphlen + PIM_REG_MINLEN);
3320 if (mcp == NULL) {
3321 log(LOG_ERR,
3322 "pim_input: pim register: could not copy register head\n");
3323 m_freem(m);
3324 return;
3325 }
3314 * outer_iphdr + pimhdr + reghdr + encap_iphdr
3315 * to pass to the daemon later, so it can take the appropriate
3316 * actions (e.g., send back PIM_REGISTER_STOP).
3317 * XXX: here m->m_data points to the outer IP header.
3318 */
3319 mcp = m_copy(m, 0, iphlen + PIM_REG_MINLEN);
3320 if (mcp == NULL) {
3321 log(LOG_ERR,
3322 "pim_input: pim register: could not copy register head\n");
3323 m_freem(m);
3324 return;
3325 }
3326
3326
3327 /* Keep statistics */
3328 /* XXX: registers_bytes include only the encap. mcast pkt */
3329 pimstat.pims_rcv_registers_msgs++;
3330 pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len);
3327 /* Keep statistics */
3328 /* XXX: registers_bytes include only the encap. mcast pkt */
3329 pimstat.pims_rcv_registers_msgs++;
3330 pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len);
3331
3331
3332 /*
3333 * forward the inner ip packet; point m_data at the inner ip.
3334 */
3335 m_adj(m, iphlen + PIM_MINLEN);
3332 /*
3333 * forward the inner ip packet; point m_data at the inner ip.
3334 */
3335 m_adj(m, iphlen + PIM_MINLEN);
3336
3336
3337 if (mrtdebug & DEBUG_PIM) {
3338 log(LOG_DEBUG,
3339 "pim_input: forwarding decapsulated register: "
3340 "src %lx, dst %lx, vif %d\n",
3341 (u_long)ntohl(encap_ip->ip_src.s_addr),
3342 (u_long)ntohl(encap_ip->ip_dst.s_addr),
3343 reg_vif_num);
3344 }
3345 /* NB: vifp was collected above; can it change on us? */
3346 if_simloop(vifp, m, dst.sin_family, 0);
3337 if (mrtdebug & DEBUG_PIM) {
3338 log(LOG_DEBUG,
3339 "pim_input: forwarding decapsulated register: "
3340 "src %lx, dst %lx, vif %d\n",
3341 (u_long)ntohl(encap_ip->ip_src.s_addr),
3342 (u_long)ntohl(encap_ip->ip_dst.s_addr),
3343 reg_vif_num);
3344 }
3345 /* NB: vifp was collected above; can it change on us? */
3346 if_simloop(vifp, m, dst.sin_family, 0);
3347
3347
3348 /* prepare the register head to send to the mrouting daemon */
3349 m = mcp;
3350 }
3351
3348 /* prepare the register head to send to the mrouting daemon */
3349 m = mcp;
3350 }
3351
3352pim_input_to_daemon:
3352pim_input_to_daemon:
3353 /*
3354 * Pass the PIM message up to the daemon; if it is a Register message,
3355 * pass the 'head' only up to the daemon. This includes the
3356 * outer IP header, PIM header, PIM-Register header and the
3357 * inner IP header.
3358 * XXX: the outer IP header pkt size of a Register is not adjust to
3359 * reflect the fact that the inner multicast data is truncated.
3360 */

--- 66 unchanged lines hidden ---
3353 /*
3354 * Pass the PIM message up to the daemon; if it is a Register message,
3355 * pass the 'head' only up to the daemon. This includes the
3356 * outer IP header, PIM header, PIM-Register header and the
3357 * inner IP header.
3358 * XXX: the outer IP header pkt size of a Register is not adjust to
3359 * reflect the fact that the inner multicast data is truncated.
3360 */

--- 66 unchanged lines hidden ---