Skip to content

Commit 449e8a8

Browse files
committed
icmp6: reply to multicast echo requests with link local address
When receiving ICMPv6 echo request packets with a multicast destination address, grout currently tries to reply with a multicast source address which is not valid. Use the link local address of the receiving interface as source address instead. Signed-off-by: Robin Jarry <[email protected]>
1 parent 04f8a3a commit 449e8a8

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

modules/ip6/control/address.c

+15
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ struct nexthop *addr6_get_preferred(uint16_t iface_id, const struct rte_ipv6_add
5959
return pref;
6060
}
6161

62+
struct nexthop *addr6_get_linklocal(uint16_t iface_id) {
63+
struct hoplist *addrs = addr6_get_all(iface_id);
64+
struct nexthop *nh;
65+
66+
if (addrs ==NULL)
67+
return NULL;
68+
69+
gr_vec_foreach (nh, addrs->nh) {
70+
if (rte_ipv6_addr_is_linklocal(&nh->ipv6))
71+
return nh;
72+
}
73+
74+
return errno_set_null(EADDRNOTAVAIL);
75+
}
76+
6277
static struct hoplist *iface_mcast_addrs;
6378

6479
struct nexthop *mcast6_get_member(uint16_t iface_id, const struct rte_ipv6_addr *mcast) {

modules/ip6/control/gr_ip6_control.h

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct nexthop *rib6_lookup(uint16_t vrf_id, uint16_t iface_id, const struct rte
4242

4343
// get the default address for a given interface
4444
struct nexthop *addr6_get_preferred(uint16_t iface_id, const struct rte_ipv6_addr *);
45+
// get the link-local address for a given interface
46+
struct nexthop *addr6_get_linklocal(uint16_t iface_id);
4547
// get all addresses for a given interface
4648
struct hoplist *addr6_get_all(uint16_t iface_id);
4749
// determine if the given interface is member of the provided multicast address group

modules/ip6/datapath/icmp6_input.c

+16-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum {
2626
BAD_CHECKSUM,
2727
INVALID,
2828
UNSUPPORTED,
29+
NO_LOCAL_ADDR,
2930
EDGE_COUNT,
3031
};
3132

@@ -57,8 +58,19 @@ icmp6_input_process(struct rte_graph *graph, struct rte_node *node, void **objs,
5758
goto next;
5859
}
5960
icmp6->type = ICMP6_TYPE_ECHO_REPLY;
60-
// swap source/destination addresses
61-
tmp_ip = d->dst;
61+
if (rte_ipv6_addr_is_mcast(&d->dst)) {
62+
struct nexthop *local = addr6_get_linklocal(
63+
mbuf_data(mbuf)->iface->id
64+
);
65+
if (local == NULL) {
66+
next = NO_LOCAL_ADDR;
67+
goto next;
68+
}
69+
tmp_ip = local->ipv6;
70+
} else {
71+
// swap source/destination addresses
72+
tmp_ip = d->dst;
73+
}
6274
d->dst = d->src;
6375
d->src = tmp_ip;
6476
next = ICMP6_OUTPUT;
@@ -120,6 +132,7 @@ static struct rte_node_register icmp6_input_node = {
120132
[BAD_CHECKSUM] = "icmp6_input_bad_checksum",
121133
[INVALID] = "icmp6_input_invalid",
122134
[UNSUPPORTED] = "icmp6_input_unsupported",
135+
[NO_LOCAL_ADDR] = "icmp6_input_no_local_addr",
123136
},
124137
};
125138

@@ -134,3 +147,4 @@ GR_NODE_REGISTER(icmp6_input_info);
134147
GR_DROP_REGISTER(icmp6_input_bad_checksum);
135148
GR_DROP_REGISTER(icmp6_input_invalid);
136149
GR_DROP_REGISTER(icmp6_input_unsupported);
150+
GR_DROP_REGISTER(icmp6_input_no_local_addr);

0 commit comments

Comments
 (0)