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 --- |