mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
netconsole: move local_ip/remote_ip/ipv6 to netconsole_target
With netpoll_setup() and the packet-building path now living in netconsole, local_ip, remote_ip and ipv6 in struct netpoll are read and written only by netconsole. No other netpoll user touches them. Move the three fields into netconsole_target and switch the packet builders and setup helpers to take the target instead of the netpoll handle. struct netpoll is left holding only the device-binding state that the shared netpoll transport needs. Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: Gustavo Luiz Duarte <gustavold@gmail.com> Link: https://patch.msgid.link/20260724-netconsole_move_more_final-v1-8-a5f7691db81c@debian.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
cf6de67ba4
commit
a111639647
|
|
@ -177,9 +177,10 @@ enum target_state {
|
|||
* @np: The netpoll structure for this target.
|
||||
* Contains the other userspace visible parameters:
|
||||
* dev_name (read-write)
|
||||
* local_ip (read-write)
|
||||
* remote_ip (read-write)
|
||||
* local_mac (read-only)
|
||||
* @local_ip: Source IP address of the target (read-write).
|
||||
* @remote_ip: Destination IP address of the target (read-write).
|
||||
* @ipv6: Whether the target addresses are IPv6 (read-write).
|
||||
* @local_port: Source UDP port of the target (read-write).
|
||||
* @remote_port: Destination UDP port of the target (read-write).
|
||||
* @remote_mac: Destination ethernet address of the target (read-write).
|
||||
|
|
@ -210,6 +211,8 @@ struct netconsole_target {
|
|||
bool extended;
|
||||
bool release;
|
||||
struct netpoll np;
|
||||
union inet_addr local_ip, remote_ip;
|
||||
bool ipv6;
|
||||
u16 local_port, remote_port;
|
||||
u8 remote_mac[ETH_ALEN];
|
||||
/* protected by target_list_lock; +1 gives scnprintf() room for its
|
||||
|
|
@ -370,11 +373,13 @@ static char *netcons_egress_dev(struct netpoll *np, char *buf, size_t bufsz)
|
|||
}
|
||||
|
||||
/*
|
||||
* Take the IPv6 from ndev and populate local_ip structure in netpoll
|
||||
* Populate the target's local_ip with the IPv6 address from ndev.
|
||||
*/
|
||||
static int netcons_take_ipv6(struct netpoll *np, struct net_device *ndev)
|
||||
static int netcons_take_ipv6(struct netconsole_target *nt,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
char buf[MAC_ADDR_STR_LEN + 1];
|
||||
struct netpoll *np = &nt->np;
|
||||
int err = -EDESTADDRREQ;
|
||||
struct inet6_dev *idev;
|
||||
|
||||
|
|
@ -391,10 +396,10 @@ static int netcons_take_ipv6(struct netpoll *np, struct net_device *ndev)
|
|||
read_lock_bh(&idev->lock);
|
||||
list_for_each_entry(ifp, &idev->addr_list, if_list) {
|
||||
if (!!(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL) !=
|
||||
!!(ipv6_addr_type(&np->remote_ip.in6) & IPV6_ADDR_LINKLOCAL))
|
||||
!!(ipv6_addr_type(&nt->remote_ip.in6) & IPV6_ADDR_LINKLOCAL))
|
||||
continue;
|
||||
/* Got the IP, let's return */
|
||||
np->local_ip.in6 = ifp->addr;
|
||||
nt->local_ip.in6 = ifp->addr;
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -406,16 +411,18 @@ static int netcons_take_ipv6(struct netpoll *np, struct net_device *ndev)
|
|||
return err;
|
||||
}
|
||||
|
||||
np_info(np, "local IPv6 %pI6c\n", &np->local_ip.in6);
|
||||
np_info(np, "local IPv6 %pI6c\n", &nt->local_ip.in6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the IPv4 from ndev and populate local_ip structure in netpoll
|
||||
* Populate the target's local_ip with the IPv4 address from ndev.
|
||||
*/
|
||||
static int netcons_take_ipv4(struct netpoll *np, struct net_device *ndev)
|
||||
static int netcons_take_ipv4(struct netconsole_target *nt,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
char buf[MAC_ADDR_STR_LEN + 1];
|
||||
struct netpoll *np = &nt->np;
|
||||
const struct in_ifaddr *ifa;
|
||||
struct in_device *in_dev;
|
||||
|
||||
|
|
@ -433,34 +440,35 @@ static int netcons_take_ipv4(struct netpoll *np, struct net_device *ndev)
|
|||
return -EDESTADDRREQ;
|
||||
}
|
||||
|
||||
np->local_ip.ip = ifa->ifa_local;
|
||||
np_info(np, "local IP %pI4\n", &np->local_ip.ip);
|
||||
nt->local_ip.ip = ifa->ifa_local;
|
||||
np_info(np, "local IP %pI4\n", &nt->local_ip.ip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether the caller left np->local_ip unset, so that
|
||||
* Test whether the caller left nt->local_ip unset, so that
|
||||
* netcons_netpoll_setup() should auto-populate it from the egress device.
|
||||
*
|
||||
* np->local_ip is a union of __be32 (IPv4) and struct in6_addr (IPv6),
|
||||
* nt->local_ip is a union of __be32 (IPv4) and struct in6_addr (IPv6),
|
||||
* so an IPv6 address whose first 4 bytes are zero (e.g. ::1, ::2,
|
||||
* IPv4-mapped ::ffff:a.b.c.d) must not be tested via the IPv4 arm —
|
||||
* doing so would misclassify a caller-supplied address as unset and
|
||||
* silently overwrite it with whatever address the device exposes.
|
||||
*/
|
||||
static bool netcons_local_ip_unset(const struct netpoll *np)
|
||||
static bool netcons_local_ip_unset(const struct netconsole_target *nt)
|
||||
{
|
||||
if (np->ipv6)
|
||||
return ipv6_addr_any(&np->local_ip.in6);
|
||||
return !np->local_ip.ip;
|
||||
if (nt->ipv6)
|
||||
return ipv6_addr_any(&nt->local_ip.in6);
|
||||
return !nt->local_ip.ip;
|
||||
}
|
||||
|
||||
static int netcons_netpoll_setup(struct netpoll *np)
|
||||
static int netcons_netpoll_setup(struct netconsole_target *nt)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
char buf[MAC_ADDR_STR_LEN + 1];
|
||||
struct net_device *ndev = NULL;
|
||||
struct netpoll *np = &nt->np;
|
||||
bool ip_overwritten = false;
|
||||
int err;
|
||||
|
||||
|
|
@ -500,13 +508,13 @@ static int netcons_netpoll_setup(struct netpoll *np)
|
|||
rtnl_lock();
|
||||
}
|
||||
|
||||
if (netcons_local_ip_unset(np)) {
|
||||
if (!np->ipv6) {
|
||||
err = netcons_take_ipv4(np, ndev);
|
||||
if (netcons_local_ip_unset(nt)) {
|
||||
if (!nt->ipv6) {
|
||||
err = netcons_take_ipv4(nt, ndev);
|
||||
if (err)
|
||||
goto put;
|
||||
} else {
|
||||
err = netcons_take_ipv6(np, ndev);
|
||||
err = netcons_take_ipv6(nt, ndev);
|
||||
if (err)
|
||||
goto put;
|
||||
}
|
||||
|
|
@ -529,7 +537,7 @@ static int netcons_netpoll_setup(struct netpoll *np)
|
|||
put:
|
||||
DEBUG_NET_WARN_ON_ONCE(np->dev);
|
||||
if (ip_overwritten)
|
||||
memset(&np->local_ip, 0, sizeof(np->local_ip));
|
||||
memset(&nt->local_ip, 0, sizeof(nt->local_ip));
|
||||
netdev_put(ndev, &np->dev_tracker);
|
||||
unlock:
|
||||
rtnl_unlock();
|
||||
|
|
@ -546,7 +554,7 @@ static void resume_target(struct netconsole_target *nt)
|
|||
*/
|
||||
netconsole_skb_pool_init(nt);
|
||||
|
||||
if (netcons_netpoll_setup(&nt->np)) {
|
||||
if (netcons_netpoll_setup(nt)) {
|
||||
/* netpoll fails setup once, do not try again. */
|
||||
netconsole_skb_pool_flush(nt);
|
||||
nt->state = STATE_DISABLED;
|
||||
|
|
@ -691,17 +699,17 @@ static void netconsole_print_banner(struct netconsole_target *nt)
|
|||
struct netpoll *np = &nt->np;
|
||||
|
||||
np_info(np, "local port %d\n", nt->local_port);
|
||||
if (np->ipv6)
|
||||
np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.in6);
|
||||
if (nt->ipv6)
|
||||
np_info(np, "local IPv6 address %pI6c\n", &nt->local_ip.in6);
|
||||
else
|
||||
np_info(np, "local IPv4 address %pI4\n", &np->local_ip.ip);
|
||||
np_info(np, "local IPv4 address %pI4\n", &nt->local_ip.ip);
|
||||
np_info(np, "interface name '%s'\n", np->dev_name);
|
||||
np_info(np, "local ethernet address '%pM'\n", np->dev_mac);
|
||||
np_info(np, "remote port %d\n", nt->remote_port);
|
||||
if (np->ipv6)
|
||||
np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.in6);
|
||||
if (nt->ipv6)
|
||||
np_info(np, "remote IPv6 address %pI6c\n", &nt->remote_ip.in6);
|
||||
else
|
||||
np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
|
||||
np_info(np, "remote IPv4 address %pI4\n", &nt->remote_ip.ip);
|
||||
np_info(np, "remote ethernet address %pM\n", nt->remote_mac);
|
||||
}
|
||||
|
||||
|
|
@ -832,20 +840,20 @@ static ssize_t local_ip_show(struct config_item *item, char *buf)
|
|||
{
|
||||
struct netconsole_target *nt = to_target(item);
|
||||
|
||||
if (nt->np.ipv6)
|
||||
return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6);
|
||||
if (nt->ipv6)
|
||||
return sysfs_emit(buf, "%pI6c\n", &nt->local_ip.in6);
|
||||
else
|
||||
return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip);
|
||||
return sysfs_emit(buf, "%pI4\n", &nt->local_ip);
|
||||
}
|
||||
|
||||
static ssize_t remote_ip_show(struct config_item *item, char *buf)
|
||||
{
|
||||
struct netconsole_target *nt = to_target(item);
|
||||
|
||||
if (nt->np.ipv6)
|
||||
return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6);
|
||||
if (nt->ipv6)
|
||||
return sysfs_emit(buf, "%pI6c\n", &nt->remote_ip.in6);
|
||||
else
|
||||
return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip);
|
||||
return sysfs_emit(buf, "%pI4\n", &nt->remote_ip);
|
||||
}
|
||||
|
||||
static ssize_t local_mac_show(struct config_item *item, char *buf)
|
||||
|
|
@ -1025,7 +1033,7 @@ static ssize_t enabled_store(struct config_item *item,
|
|||
*/
|
||||
netconsole_skb_pool_init(nt);
|
||||
|
||||
ret = netcons_netpoll_setup(&nt->np);
|
||||
ret = netcons_netpoll_setup(nt);
|
||||
if (ret) {
|
||||
netconsole_skb_pool_flush(nt);
|
||||
goto out_unlock;
|
||||
|
|
@ -1199,10 +1207,10 @@ static ssize_t local_ip_store(struct config_item *item, const char *buf,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
ipv6 = netpoll_parse_ip_addr(buf, &nt->np.local_ip);
|
||||
ipv6 = netpoll_parse_ip_addr(buf, &nt->local_ip);
|
||||
if (ipv6 == -1)
|
||||
goto out_unlock;
|
||||
nt->np.ipv6 = !!ipv6;
|
||||
nt->ipv6 = !!ipv6;
|
||||
|
||||
ret = count;
|
||||
out_unlock:
|
||||
|
|
@ -1224,10 +1232,10 @@ static ssize_t remote_ip_store(struct config_item *item, const char *buf,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
ipv6 = netpoll_parse_ip_addr(buf, &nt->np.remote_ip);
|
||||
ipv6 = netpoll_parse_ip_addr(buf, &nt->remote_ip);
|
||||
if (ipv6 == -1)
|
||||
goto out_unlock;
|
||||
nt->np.ipv6 = !!ipv6;
|
||||
nt->ipv6 = !!ipv6;
|
||||
|
||||
ret = count;
|
||||
out_unlock:
|
||||
|
|
@ -2027,8 +2035,8 @@ static struct sk_buff *find_skb(struct netconsole_target *nt, int len,
|
|||
return skb;
|
||||
}
|
||||
|
||||
static void netpoll_udp_checksum(struct netpoll *np, struct sk_buff *skb,
|
||||
int len)
|
||||
static void netpoll_udp_checksum(struct netconsole_target *nt,
|
||||
struct sk_buff *skb, int len)
|
||||
{
|
||||
struct udphdr *udph;
|
||||
int udp_len;
|
||||
|
|
@ -2038,14 +2046,14 @@ static void netpoll_udp_checksum(struct netpoll *np, struct sk_buff *skb,
|
|||
|
||||
/* check needs to be set, since it will be consumed in csum_partial */
|
||||
udph->check = 0;
|
||||
if (np->ipv6)
|
||||
udph->check = csum_ipv6_magic(&np->local_ip.in6,
|
||||
&np->remote_ip.in6,
|
||||
if (nt->ipv6)
|
||||
udph->check = csum_ipv6_magic(&nt->local_ip.in6,
|
||||
&nt->remote_ip.in6,
|
||||
udp_len, IPPROTO_UDP,
|
||||
csum_partial(udph, udp_len, 0));
|
||||
else
|
||||
udph->check = csum_tcpudp_magic(np->local_ip.ip,
|
||||
np->remote_ip.ip,
|
||||
udph->check = csum_tcpudp_magic(nt->local_ip.ip,
|
||||
nt->remote_ip.ip,
|
||||
udp_len, IPPROTO_UDP,
|
||||
csum_partial(udph, udp_len, 0));
|
||||
if (udph->check == 0)
|
||||
|
|
@ -2054,7 +2062,6 @@ static void netpoll_udp_checksum(struct netpoll *np, struct sk_buff *skb,
|
|||
|
||||
static void push_udp(struct netconsole_target *nt, struct sk_buff *skb, int len)
|
||||
{
|
||||
struct netpoll *np = &nt->np;
|
||||
struct udphdr *udph;
|
||||
int udp_len;
|
||||
|
||||
|
|
@ -2068,7 +2075,7 @@ static void push_udp(struct netconsole_target *nt, struct sk_buff *skb, int len)
|
|||
udph->dest = htons(nt->remote_port);
|
||||
udp_set_len_short(udph, udp_len);
|
||||
|
||||
netpoll_udp_checksum(np, skb, len);
|
||||
netpoll_udp_checksum(nt, skb, len);
|
||||
}
|
||||
|
||||
static void push_eth(struct netconsole_target *nt, struct sk_buff *skb)
|
||||
|
|
@ -2080,13 +2087,14 @@ static void push_eth(struct netconsole_target *nt, struct sk_buff *skb)
|
|||
skb_reset_mac_header(skb);
|
||||
ether_addr_copy(eth->h_source, np->dev->dev_addr);
|
||||
ether_addr_copy(eth->h_dest, nt->remote_mac);
|
||||
if (np->ipv6)
|
||||
if (nt->ipv6)
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
else
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
}
|
||||
|
||||
static void push_ipv4(struct netpoll *np, struct sk_buff *skb, int len)
|
||||
static void push_ipv4(struct netconsole_target *nt, struct sk_buff *skb,
|
||||
int len)
|
||||
{
|
||||
static atomic_t ip_ident;
|
||||
struct iphdr *iph;
|
||||
|
|
@ -2107,13 +2115,14 @@ static void push_ipv4(struct netpoll *np, struct sk_buff *skb, int len)
|
|||
iph->ttl = 64;
|
||||
iph->protocol = IPPROTO_UDP;
|
||||
iph->check = 0;
|
||||
put_unaligned(np->local_ip.ip, &iph->saddr);
|
||||
put_unaligned(np->remote_ip.ip, &iph->daddr);
|
||||
put_unaligned(nt->local_ip.ip, &iph->saddr);
|
||||
put_unaligned(nt->remote_ip.ip, &iph->daddr);
|
||||
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
}
|
||||
|
||||
static void push_ipv6(struct netpoll *np, struct sk_buff *skb, int len)
|
||||
static void push_ipv6(struct netconsole_target *nt, struct sk_buff *skb,
|
||||
int len)
|
||||
{
|
||||
struct ipv6hdr *ip6h;
|
||||
|
||||
|
|
@ -2130,8 +2139,8 @@ static void push_ipv6(struct netpoll *np, struct sk_buff *skb, int len)
|
|||
ip6h->payload_len = htons(sizeof(struct udphdr) + len);
|
||||
ip6h->nexthdr = IPPROTO_UDP;
|
||||
ip6h->hop_limit = 32;
|
||||
ip6h->saddr = np->local_ip.in6;
|
||||
ip6h->daddr = np->remote_ip.in6;
|
||||
ip6h->saddr = nt->local_ip.in6;
|
||||
ip6h->daddr = nt->remote_ip.in6;
|
||||
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
}
|
||||
|
|
@ -2147,7 +2156,7 @@ static int netpoll_send_udp(struct netconsole_target *nt, const char *msg,
|
|||
WARN_ON_ONCE(!irqs_disabled());
|
||||
|
||||
udp_len = len + sizeof(struct udphdr);
|
||||
if (np->ipv6)
|
||||
if (nt->ipv6)
|
||||
ip_len = udp_len + sizeof(struct ipv6hdr);
|
||||
else
|
||||
ip_len = udp_len + sizeof(struct iphdr);
|
||||
|
|
@ -2163,10 +2172,10 @@ static int netpoll_send_udp(struct netconsole_target *nt, const char *msg,
|
|||
skb_put(skb, len);
|
||||
|
||||
push_udp(nt, skb, len);
|
||||
if (np->ipv6)
|
||||
push_ipv6(np, skb, len);
|
||||
if (nt->ipv6)
|
||||
push_ipv6(nt, skb, len);
|
||||
else
|
||||
push_ipv4(np, skb, len);
|
||||
push_ipv4(nt, skb, len);
|
||||
push_eth(nt, skb);
|
||||
skb->dev = np->dev;
|
||||
|
||||
|
|
@ -2505,11 +2514,11 @@ static int netconsole_parser_cmdline(struct netconsole_target *nt, char *opt)
|
|||
if (!delim)
|
||||
goto parse_failed;
|
||||
*delim = 0;
|
||||
ipv6 = netpoll_parse_ip_addr(cur, &np->local_ip);
|
||||
ipv6 = netpoll_parse_ip_addr(cur, &nt->local_ip);
|
||||
if (ipv6 < 0)
|
||||
goto parse_failed;
|
||||
else
|
||||
np->ipv6 = (bool)ipv6;
|
||||
nt->ipv6 = (bool)ipv6;
|
||||
cur = delim;
|
||||
}
|
||||
cur++;
|
||||
|
|
@ -2551,13 +2560,13 @@ static int netconsole_parser_cmdline(struct netconsole_target *nt, char *opt)
|
|||
if (!delim)
|
||||
goto parse_failed;
|
||||
*delim = 0;
|
||||
ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip);
|
||||
ipv6 = netpoll_parse_ip_addr(cur, &nt->remote_ip);
|
||||
if (ipv6 < 0)
|
||||
goto parse_failed;
|
||||
else if (ipversion_set && np->ipv6 != (bool)ipv6)
|
||||
else if (ipversion_set && nt->ipv6 != (bool)ipv6)
|
||||
goto parse_failed;
|
||||
else
|
||||
np->ipv6 = (bool)ipv6;
|
||||
nt->ipv6 = (bool)ipv6;
|
||||
cur = delim + 1;
|
||||
|
||||
if (*cur != 0) {
|
||||
|
|
@ -2615,7 +2624,7 @@ static struct netconsole_target *alloc_param_target(char *target_config,
|
|||
*/
|
||||
netconsole_skb_pool_init(nt);
|
||||
|
||||
err = netcons_netpoll_setup(&nt->np);
|
||||
err = netcons_netpoll_setup(nt);
|
||||
if (err) {
|
||||
pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",
|
||||
NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ struct netpoll {
|
|||
char dev_name[IFNAMSIZ];
|
||||
u8 dev_mac[ETH_ALEN];
|
||||
const char *name;
|
||||
|
||||
union inet_addr local_ip, remote_ip;
|
||||
bool ipv6;
|
||||
};
|
||||
|
||||
#define np_info(np, fmt, ...) \
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user