Skip to content

Commit eddd0f8

Browse files
AlphixNoltari
authored andcommitted
router: improve send_router_advert()
Remove a bunch of memory (re)allocations which are performed on every single RA. Also remove some pointless casts. Signed-off-by: David Härdeman <david@hardeman.nu> Link: #358 Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
1 parent 35f0e05 commit eddd0f8

File tree

1 file changed

+21
-41
lines changed

1 file changed

+21
-41
lines changed

src/router.c

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
684684

685685
adv.mtu.nd_opt_mtu_mtu = htonl(iface->ra_mtu);
686686

687-
iov[IOV_RA_ADV].iov_base = (char *)&adv;
687+
iov[IOV_RA_ADV].iov_base = &adv;
688688
iov[IOV_RA_ADV].iov_len = sizeof(adv);
689689

690690
valid_addr_cnt = (iface->timer_rs.cb /* if not shutdown */ ? iface->addr6_len : 0);
@@ -735,6 +735,10 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
735735
}
736736

737737
/* Construct Prefix Information options */
738+
if (total_addr_cnt > 0) {
739+
pfxs = alloca(total_addr_cnt * sizeof(*pfxs));
740+
memset(pfxs, 0, total_addr_cnt * sizeof(*pfxs));
741+
}
738742
for (size_t i = 0; i < total_addr_cnt; ++i) {
739743
struct odhcpd_ipaddr *addr = &addrs[i];
740744
struct nd_opt_prefix_info *p = NULL;
@@ -762,19 +766,8 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
762766
p = &pfxs[j];
763767
}
764768

765-
if (!p) {
766-
struct nd_opt_prefix_info *tmp;
767-
768-
tmp = realloc(pfxs, sizeof(*pfxs) * (pfxs_cnt + 1));
769-
if (!tmp) {
770-
error("Realloc failed for RA prefix option on %s", iface->name);
771-
continue;
772-
}
773-
774-
pfxs = tmp;
769+
if (!p)
775770
p = &pfxs[pfxs_cnt++];
776-
memset(p, 0, sizeof(*p));
777-
}
778771

779772
if (addr->preferred_lt > (uint32_t)now) {
780773
preferred_lt = TIME_LEFT(addr->preferred_lt, now);
@@ -860,7 +853,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
860853

861854
router_clear_duplicated_ra_pio(iface);
862855

863-
iov[IOV_RA_PFXS].iov_base = (char *)pfxs;
856+
iov[IOV_RA_PFXS].iov_base = pfxs;
864857
iov[IOV_RA_PFXS].iov_len = pfxs_cnt * sizeof(*pfxs);
865858

866859
/* Calculate periodic transmit */
@@ -938,9 +931,9 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
938931
}
939932
}
940933

941-
iov[IOV_RA_DNS].iov_base = (char *)dns;
934+
iov[IOV_RA_DNS].iov_base = dns;
942935
iov[IOV_RA_DNS].iov_len = dns_sz;
943-
iov[IOV_RA_SEARCH].iov_base = (char *)search;
936+
iov[IOV_RA_SEARCH].iov_base = search;
944937
iov[IOV_RA_SEARCH].iov_len = search_sz;
945938

946939
if (iface->pref64_length) {
@@ -955,7 +948,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
955948
(0x7 & iface->pref64_plc));
956949
memcpy(pref64->prefix, iface->pref64_prefix, sizeof(pref64->prefix));
957950
}
958-
iov[IOV_RA_PREF64].iov_base = (char *)pref64;
951+
iov[IOV_RA_PREF64].iov_base = pref64;
959952
iov[IOV_RA_PREF64].iov_len = pref64_sz;
960953

961954
if (iface->dnr_cnt) {
@@ -1003,7 +996,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
1003996
memcpy(tmp, iface->dnr[i].svc, iface->dnr[i].svc_len);
1004997
}
1005998
}
1006-
iov[IOV_RA_DNR].iov_base = (char *)dnrs;
999+
iov[IOV_RA_DNR].iov_base = dnrs;
10071000
iov[IOV_RA_DNR].iov_len = dnrs_sz;
10081001

10091002
/*
@@ -1015,25 +1008,26 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
10151008
* independent of having or not having IPv6 connectivity on the
10161009
* WAN interface.
10171010
*/
1018-
1011+
if (valid_addr_cnt > 0) {
1012+
routes = alloca(valid_addr_cnt * sizeof(*routes));
1013+
memset(routes, 0, valid_addr_cnt * sizeof(*routes));
1014+
}
10191015
for (size_t i = 0; i < valid_addr_cnt; ++i) {
10201016
struct odhcpd_ipaddr *addr = &addrs[i];
1021-
struct nd_opt_route_info *tmp;
10221017
uint32_t valid_lt;
10231018

10241019
if (addr->dprefix_len >= 64 || addr->dprefix_len == 0 || addr->valid_lt <= (uint32_t)now) {
10251020
info("Address %s (dprefix %d, valid-lifetime %u) not suitable as RA route on %s",
10261021
inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)),
10271022
addr->dprefix_len, addr->valid_lt, iface->name);
1028-
1029-
continue; /* Address not suitable */
1023+
continue;
10301024
}
10311025

10321026
if (ADDR_MATCH_PIO_FILTER(addr, iface)) {
10331027
info("Address %s filtered out as RA route on %s",
10341028
inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)),
10351029
iface->name);
1036-
continue; /* PIO filtered out of this RA */
1030+
continue;
10371031
}
10381032

10391033
if (addr->dprefix_len > 32) {
@@ -1043,15 +1037,6 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
10431037
addr->addr.in6.s6_addr32[1] = 0;
10441038
}
10451039

1046-
tmp = realloc(routes, sizeof(*routes) * (routes_cnt + 1));
1047-
if (!tmp) {
1048-
error("Realloc failed for RA route option on %s", iface->name);
1049-
continue;
1050-
}
1051-
1052-
routes = tmp;
1053-
1054-
memset(&routes[routes_cnt], 0, sizeof(*routes));
10551040
routes[routes_cnt].type = ND_OPT_ROUTE_INFO;
10561041
routes[routes_cnt].len = sizeof(*routes) / 8;
10571042
routes[routes_cnt].prefix_len = addr->dprefix_len;
@@ -1070,22 +1055,20 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
10701055
routes[routes_cnt].addr[2] = 0;
10711056
routes[routes_cnt].addr[3] = 0;
10721057

1073-
++routes_cnt;
1058+
routes_cnt++;
10741059
}
1075-
1076-
iov[IOV_RA_ROUTES].iov_base = (char *)routes;
1060+
iov[IOV_RA_ROUTES].iov_base = routes;
10771061
iov[IOV_RA_ROUTES].iov_len = routes_cnt * sizeof(*routes);
10781062

10791063
memset(&adv_interval, 0, sizeof(adv_interval));
10801064
adv_interval.nd_opt_adv_interval_type = ND_OPT_RTR_ADV_INTERVAL;
10811065
adv_interval.nd_opt_adv_interval_len = 1;
10821066
adv_interval.nd_opt_adv_interval_ival = htonl(maxival*1000);
10831067

1084-
iov[IOV_RA_ADV_INTERVAL].iov_base = (char *)&adv_interval;
1068+
iov[IOV_RA_ADV_INTERVAL].iov_base = &adv_interval;
10851069
iov[IOV_RA_ADV_INTERVAL].iov_len = adv_interval.nd_opt_adv_interval_len * 8;
10861070

10871071
/* RFC 8910 Captive Portal */
1088-
uint8_t *captive_portal_uri = (uint8_t *)iface->captive_portal_uri;
10891072
if (iface->captive_portal_uri_len > 0) {
10901073
/* compute pad so that (header + data + pad) is a multiple of 8 */
10911074
capt_portal_sz = (sizeof(struct nd_opt_capt_portal) + iface->captive_portal_uri_len + 7) & ~7;
@@ -1096,7 +1079,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
10961079
capt_portal->type = ND_OPT_CAPTIVE_PORTAL;
10971080
capt_portal->len = capt_portal_sz / 8;
10981081

1099-
memcpy(capt_portal->data, captive_portal_uri, iface->captive_portal_uri_len);
1082+
memcpy(capt_portal->data, iface->captive_portal_uri, iface->captive_portal_uri_len);
11001083
/* remaining padding bytes already set to 0x00 */
11011084
}
11021085

@@ -1120,9 +1103,6 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
11201103
}
11211104

11221105
out:
1123-
free(pfxs);
1124-
free(routes);
1125-
11261106
return msecs;
11271107
}
11281108

0 commit comments

Comments
 (0)