Lines Matching +full:- +full:- +full:target +full:- +full:list

1 // SPDX-License-Identifier: GPL-2.0-or-later
7 * This file contains the implementation of an IRQ-safe, crash-safe
13 * 2001-09-17 started by Ingo Molnar.
14 * 2003-08-11 2.6 port by Matt Mackall
17 * works non-modular
18 * 2003-09-07 rewritten with netpoll api
51 #define MAX_EXTRADATA_NAME_LEN (MAX_EXTRADATA_ENTRY_LEN - \
52 MAX_EXTRADATA_VALUE_LEN - 3)
58 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macadd…
75 /* Linked list of all configured targets */
107 /* Populate the task name (as in current->comm) in sysdata */
114 * struct netconsole_target - Represents a configured netconsole target.
115 * @list: Links this target into the target_list.
121 * @stats: Packet send stats for the target. Used for debugging.
122 * @enabled: On / off knob to enable / disable target.
123 * Visible from userspace (read-write).
126 * Also, other parameters of a target may be modified at
131 * @np: The netpoll structure for this target.
133 * dev_name (read-write)
134 * local_port (read-write)
135 * remote_port (read-write)
136 * local_ip (read-write)
137 * remote_ip (read-write)
138 * local_mac (read-only)
139 * remote_mac (read-write)
143 struct list_head list; member
149 /* bit-wise with sysdata_feature bits */
181 * never go away, so make these a no-op for them.
185 if (config_item_name(&nt->group.cg_item)) in netconsole_target_get()
186 config_group_get(&nt->group); in netconsole_target_get()
191 if (config_item_name(&nt->group.cg_item)) in netconsole_target_put()
192 config_group_put(&nt->group); in netconsole_target_put()
225 * Note that these targets get their config_item fields zeroed-out.
236 nt->extended = true; in alloc_and_init()
238 nt->release = true; in alloc_and_init()
240 nt->np.name = "netconsole"; in alloc_and_init()
241 strscpy(nt->np.dev_name, "eth0", IFNAMSIZ); in alloc_and_init()
242 nt->np.local_port = 6665; in alloc_and_init()
243 nt->np.remote_port = 6666; in alloc_and_init()
244 eth_broadcast_addr(nt->np.remote_mac); in alloc_and_init()
249 /* Clean up every target in the cleanup_list and move the clean targets back to
261 list_for_each_entry_safe(nt, tmp, &target_cleanup_list, list) { in netconsole_process_cleanups_core()
263 WARN_ON_ONCE(nt->enabled); in netconsole_process_cleanups_core()
264 do_netpoll_cleanup(&nt->np); in netconsole_process_cleanups_core()
265 /* moved the cleaned target to target_list. Need to hold both in netconsole_process_cleanups_core()
269 list_move(&nt->list, &target_list); in netconsole_process_cleanups_core()
283 * <target>/
299 * <target>/...
313 /* Do the list cleanup with the rtnl lock hold. rtnl lock is necessary because
314 * netdev might be cleaned-up by calling __netpoll_cleanup(),
332 if (s[len - 1] == '\n') in trim_newline()
333 s[len - 1] = '\0'; in trim_newline()
342 return sysfs_emit(buf, "%d\n", to_target(item)->enabled); in enabled_show()
347 return sysfs_emit(buf, "%d\n", to_target(item)->extended); in extended_show()
352 return sysfs_emit(buf, "%d\n", to_target(item)->release); in release_show()
357 return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name); in dev_name_show()
362 return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port); in local_port_show()
367 return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port); in remote_port_show()
374 if (nt->np.ipv6) in local_ip_show()
375 return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6); in local_ip_show()
377 return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip); in local_ip_show()
384 if (nt->np.ipv6) in remote_ip_show()
385 return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6); in remote_ip_show()
387 return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip); in remote_ip_show()
392 struct net_device *dev = to_target(item)->np.dev; in local_mac_show()
395 return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast); in local_mac_show()
400 return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac); in remote_mac_show()
410 start = u64_stats_fetch_begin(&nt->stats.syncp); in transmit_errors_show()
411 xmit_drop_count = u64_stats_read(&nt->stats.xmit_drop_count); in transmit_errors_show()
412 enomem_count = u64_stats_read(&nt->stats.enomem_count); in transmit_errors_show()
413 } while (u64_stats_fetch_retry(&nt->stats.syncp, start)); in transmit_errors_show()
421 struct netconsole_target *nt = to_target(item->ci_parent); in sysdata_cpu_nr_enabled_show()
425 cpu_nr_enabled = !!(nt->sysdata_fields & SYSDATA_CPU_NR); in sysdata_cpu_nr_enabled_show()
435 struct netconsole_target *nt = to_target(item->ci_parent); in sysdata_taskname_enabled_show()
439 taskname_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME); in sysdata_taskname_enabled_show()
448 struct netconsole_target *nt = to_target(item->ci_parent); in sysdata_release_enabled_show()
452 release_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME); in sysdata_release_enabled_show()
459 * This one is special -- targets created through the configfs interface
478 ret = -EINVAL; in enabled_store()
479 if (enabled == nt->enabled) { in enabled_store()
481 nt->enabled ? "started" : "stopped"); in enabled_store()
486 if (nt->release && !nt->extended) { in enabled_store()
491 if (nt->extended && !console_is_registered(&netconsole_ext)) in enabled_store()
495 * Skip netpoll_parse_options() -- all the attributes are in enabled_store()
498 netpoll_print_options(&nt->np); in enabled_store()
500 ret = netpoll_setup(&nt->np); in enabled_store()
504 nt->enabled = true; in enabled_store()
509 * nt->np.dev == NULL and nt->enabled == true in enabled_store()
513 nt->enabled = false; in enabled_store()
514 /* Remove the target from the list, while holding in enabled_store()
517 list_move(&nt->list, &target_cleanup_list); in enabled_store()
538 if (nt->enabled) { in release_store()
539 pr_err("target (%s) is enabled, disable to update parameters\n", in release_store()
540 config_item_name(&nt->group.cg_item)); in release_store()
541 ret = -EINVAL; in release_store()
549 nt->release = release; in release_store()
565 if (nt->enabled) { in extended_store()
566 pr_err("target (%s) is enabled, disable to update parameters\n", in extended_store()
567 config_item_name(&nt->group.cg_item)); in extended_store()
568 ret = -EINVAL; in extended_store()
576 nt->extended = extended; in extended_store()
589 if (nt->enabled) { in dev_name_store()
590 pr_err("target (%s) is enabled, disable to update parameters\n", in dev_name_store()
591 config_item_name(&nt->group.cg_item)); in dev_name_store()
593 return -EINVAL; in dev_name_store()
596 strscpy(nt->np.dev_name, buf, IFNAMSIZ); in dev_name_store()
597 trim_newline(nt->np.dev_name, IFNAMSIZ); in dev_name_store()
607 ssize_t ret = -EINVAL; in local_port_store()
610 if (nt->enabled) { in local_port_store()
611 pr_err("target (%s) is enabled, disable to update parameters\n", in local_port_store()
612 config_item_name(&nt->group.cg_item)); in local_port_store()
616 ret = kstrtou16(buf, 10, &nt->np.local_port); in local_port_store()
629 ssize_t ret = -EINVAL; in remote_port_store()
632 if (nt->enabled) { in remote_port_store()
633 pr_err("target (%s) is enabled, disable to update parameters\n", in remote_port_store()
634 config_item_name(&nt->group.cg_item)); in remote_port_store()
638 ret = kstrtou16(buf, 10, &nt->np.remote_port); in remote_port_store()
651 ssize_t ret = -EINVAL; in local_ip_store()
654 if (nt->enabled) { in local_ip_store()
655 pr_err("target (%s) is enabled, disable to update parameters\n", in local_ip_store()
656 config_item_name(&nt->group.cg_item)); in local_ip_store()
663 if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) { in local_ip_store()
668 nt->np.ipv6 = true; in local_ip_store()
672 if (!nt->np.ipv6) in local_ip_store()
673 nt->np.local_ip.ip = in_aton(buf); in local_ip_store()
688 ssize_t ret = -EINVAL; in remote_ip_store()
691 if (nt->enabled) { in remote_ip_store()
692 pr_err("target (%s) is enabled, disable to update parameters\n", in remote_ip_store()
693 config_item_name(&nt->group.cg_item)); in remote_ip_store()
700 if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) { in remote_ip_store()
705 nt->np.ipv6 = true; in remote_ip_store()
709 if (!nt->np.ipv6) in remote_ip_store()
710 nt->np.remote_ip.ip = in_aton(buf); in remote_ip_store()
731 entries = list_count_nodes(&nt->userdata_group.cg_children); in count_extradata_entries()
733 if (nt->sysdata_fields & SYSDATA_CPU_NR) in count_extradata_entries()
735 if (nt->sysdata_fields & SYSDATA_TASKNAME) in count_extradata_entries()
737 if (nt->sysdata_fields & SYSDATA_RELEASE) in count_extradata_entries()
748 ssize_t ret = -EINVAL; in remote_mac_store()
751 if (nt->enabled) { in remote_mac_store()
752 pr_err("target (%s) is enabled, disable to update parameters\n", in remote_mac_store()
753 config_item_name(&nt->group.cg_item)); in remote_mac_store()
761 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); in remote_mac_store()
792 netconsole_group = to_config_group(ud->group.cg_item.ci_parent); in userdata_to_target()
793 return to_target(&netconsole_group->cg_item); in userdata_to_target()
798 return sysfs_emit(buf, "%s\n", &(to_userdatum(item)->value[0])); in userdatum_value_show()
807 nt->userdata_length = 0; in update_userdata()
808 nt->extradata_complete[0] = 0; in update_userdata()
810 list_for_each(entry, &nt->userdata_group.cg_children) { in update_userdata()
822 if (strnlen(udm_item->value, MAX_EXTRADATA_VALUE_LEN) == 0) in update_userdata()
829 complete_idx += scnprintf(&nt->extradata_complete[complete_idx], in update_userdata()
831 item->ci_name, udm_item->value); in update_userdata()
833 nt->userdata_length = strnlen(nt->extradata_complete, in update_userdata()
834 sizeof(nt->extradata_complete)); in update_userdata()
846 return -EMSGSIZE; in userdatum_value_store()
850 ret = strscpy(udm->value, buf, sizeof(udm->value)); in userdatum_value_store()
853 trim_newline(udm->value, sizeof(udm->value)); in userdatum_value_store()
855 ud = to_userdata(item->ci_parent); in userdatum_value_store()
864 /* disable_sysdata_feature - Disable sysdata feature and clean sysdata
865 * @nt: target that is disabling the feature
871 nt->sysdata_fields &= ~feature; in disable_sysdata_feature()
872 nt->extradata_complete[nt->userdata_length] = 0; in disable_sysdata_feature()
878 struct netconsole_target *nt = to_target(item->ci_parent); in sysdata_release_enabled_store()
887 curr = !!(nt->sysdata_fields & SYSDATA_RELEASE); in sysdata_release_enabled_store()
893 ret = -ENOSPC; in sysdata_release_enabled_store()
898 nt->sysdata_fields |= SYSDATA_RELEASE; in sysdata_release_enabled_store()
912 struct netconsole_target *nt = to_target(item->ci_parent); in sysdata_taskname_enabled_store()
921 curr = !!(nt->sysdata_fields & SYSDATA_TASKNAME); in sysdata_taskname_enabled_store()
927 ret = -ENOSPC; in sysdata_taskname_enabled_store()
932 nt->sysdata_fields |= SYSDATA_TASKNAME; in sysdata_taskname_enabled_store()
947 struct netconsole_target *nt = to_target(item->ci_parent); in sysdata_cpu_nr_enabled_store()
956 curr = !!(nt->sysdata_fields & SYSDATA_CPU_NR); in sysdata_cpu_nr_enabled_store()
966 ret = -ENOSPC; in sysdata_cpu_nr_enabled_store()
971 nt->sysdata_fields |= SYSDATA_CPU_NR; in sysdata_cpu_nr_enabled_store()
1019 return ERR_PTR(-ENAMETOOLONG); in userdatum_make_item()
1021 ud = to_userdata(&group->cg_item); in userdatum_make_item()
1024 return ERR_PTR(-ENOSPC); in userdatum_make_item()
1028 return ERR_PTR(-ENOMEM); in userdatum_make_item()
1030 config_item_init_type_name(&udm->item, name, &userdatum_type); in userdatum_make_item()
1031 return &udm->item; in userdatum_make_item()
1039 ud = to_userdata(&group->cg_item); in userdatum_drop()
1116 config_group_init_type_name(&nt->group, name, &netconsole_target_type); in init_target_config_group()
1117 config_group_init_type_name(&nt->userdata_group, "userdata", in init_target_config_group()
1119 configfs_add_default_group(&nt->userdata_group, &nt->group); in init_target_config_group()
1128 list_for_each_entry(nt, &target_list, list) { in find_cmdline_target()
1129 if (!strcmp(nt->group.cg_item.ci_name, name)) { in find_cmdline_target()
1149 /* Checking if a target by this name was created at boot time. If so, in make_netconsole_target()
1150 * attach a configfs entry to that target. This enables dynamic in make_netconsole_target()
1158 return &nt->group; in make_netconsole_target()
1164 return ERR_PTR(-ENOMEM); in make_netconsole_target()
1171 list_add(&nt->list, &target_list); in make_netconsole_target()
1174 return &nt->group; in make_netconsole_target()
1184 list_del(&nt->list); in drop_netconsole_target()
1188 * The target may have never been enabled, or was manually disabled in drop_netconsole_target()
1191 if (nt->enabled) in drop_netconsole_target()
1192 netpoll_cleanup(&nt->np); in drop_netconsole_target()
1194 config_item_put(&nt->group.cg_item); in drop_netconsole_target()
1230 return scnprintf(&nt->extradata_complete[offset], in sysdata_append_cpu_nr()
1237 return scnprintf(&nt->extradata_complete[offset], in sysdata_append_taskname()
1239 current->comm); in sysdata_append_taskname()
1244 return scnprintf(&nt->extradata_complete[offset], in sysdata_append_release()
1246 init_utsname()->release); in sysdata_append_release()
1250 * prepare_extradata - append sysdata at extradata_complete in runtime
1251 * @nt: target to send message to
1261 extradata_len = nt->userdata_length; in prepare_extradata()
1263 if (!(nt->sysdata_fields & fields)) in prepare_extradata()
1266 if (nt->sysdata_fields & SYSDATA_CPU_NR) in prepare_extradata()
1268 if (nt->sysdata_fields & SYSDATA_TASKNAME) in prepare_extradata()
1270 if (nt->sysdata_fields & SYSDATA_RELEASE) in prepare_extradata()
1301 list_for_each_entry_safe(nt, tmp, &target_list, list) { in netconsole_netdev_event()
1303 if (nt->np.dev == dev) { in netconsole_netdev_event()
1306 strscpy(nt->np.dev_name, dev->name, IFNAMSIZ); in netconsole_netdev_event()
1311 nt->enabled = false; in netconsole_netdev_event()
1312 list_move(&nt->list, &target_cleanup_list); in netconsole_netdev_event()
1336 dev->name, msg); in netconsole_netdev_event()
1353 * send_udp - Wrapper for netpoll_send_udp that counts errors
1354 * @nt: target to send message to
1359 * occurred it increments statistics in nt->stats accordingly.
1364 int result = netpoll_send_udp(&nt->np, msg, len); in send_udp()
1368 u64_stats_update_begin(&nt->stats.syncp); in send_udp()
1369 u64_stats_inc(&nt->stats.xmit_drop_count); in send_udp()
1370 u64_stats_update_end(&nt->stats.syncp); in send_udp()
1371 } else if (result == -ENOMEM) { in send_udp()
1372 u64_stats_update_begin(&nt->stats.syncp); in send_udp()
1373 u64_stats_inc(&nt->stats.enomem_count); in send_udp()
1374 u64_stats_update_end(&nt->stats.syncp); in send_udp()
1388 extradata = nt->extradata_complete; in send_msg_no_fragmentation()
1392 release = init_utsname()->release; in send_msg_no_fragmentation()
1394 scnprintf(nt->buf, MAX_PRINT_CHUNK, "%s,%s", release, msg); in send_msg_no_fragmentation()
1397 memcpy(nt->buf, msg, msg_len); in send_msg_no_fragmentation()
1401 msg_len += scnprintf(&nt->buf[msg_len], in send_msg_no_fragmentation()
1402 MAX_PRINT_CHUNK - msg_len, in send_msg_no_fragmentation()
1405 send_udp(nt, nt->buf, msg_len); in send_msg_no_fragmentation()
1412 release = init_utsname()->release; in append_release()
1425 extradata = nt->extradata_complete; in send_fragmented_body()
1446 this_header += scnprintf(nt->buf + this_header, in send_fragmented_body()
1447 MAX_PRINT_CHUNK - this_header, in send_fragmented_body()
1453 this_chunk = min(msgbody_len - offset, in send_fragmented_body()
1454 MAX_PRINT_CHUNK - this_header); in send_fragmented_body()
1457 memcpy(nt->buf + this_header, msgbody + offset, in send_fragmented_body()
1475 sent_extradata = (offset + this_offset) - msgbody_len; in send_fragmented_body()
1482 this_chunk = min(extradata_len - sent_extradata, in send_fragmented_body()
1483 MAX_PRINT_CHUNK - preceding_bytes); in send_fragmented_body()
1492 memcpy(nt->buf + this_header + this_offset, in send_fragmented_body()
1498 send_udp(nt, nt->buf, this_header + this_offset); in send_fragmented_body()
1517 header_len = msgbody - msg; in send_msg_fragmented()
1518 msgbody_len = msg_len - header_len - 1; in send_msg_fragmented()
1523 * "ncfrag=<byte-offset>/<total-bytes>" in send_msg_fragmented()
1526 append_release(nt->buf); in send_msg_fragmented()
1529 memcpy(nt->buf + release_len, msg, header_len); in send_msg_fragmented()
1540 * send_ext_msg_udp - send extended log message to target
1541 * @nt: target to send message to
1557 if (nt->release) in send_ext_msg_udp()
1558 release_len = strlen(init_utsname()->release) + 1; in send_ext_msg_udp()
1577 list_for_each_entry(nt, &target_list, list) in write_ext_msg()
1578 if (nt->extended && nt->enabled && netif_running(nt->np.dev)) in write_ext_msg()
1597 list_for_each_entry(nt, &target_list, list) { in write_msg()
1598 if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) { in write_msg()
1600 * We nest this inside the for-each-target loop above in write_msg()
1602 * at least one target if we die inside here, instead in write_msg()
1603 * of unnecessarily keeping all targets in lock-step. in write_msg()
1610 left -= frag; in write_msg()
1617 /* Allocate new target (from boot/module param) and setup netpoll for it */
1626 err = -ENOMEM; in alloc_param_target()
1631 nt->extended = true; in alloc_param_target()
1636 if (!nt->extended) { in alloc_param_target()
1638 err = -EINVAL; in alloc_param_target()
1641 nt->release = true; in alloc_param_target()
1646 err = netpoll_parse_options(&nt->np, target_config); in alloc_param_target()
1650 err = netpoll_setup(&nt->np); in alloc_param_target()
1656 * otherwise, keep the target in the list, but disabled. in alloc_param_target()
1660 nt->enabled = true; in alloc_param_target()
1671 /* Cleanup netpoll for given target (from boot/module param) and free it */
1674 netpoll_cleanup(&nt->np); in free_param_target()
1710 if (nt->extended) { in init_netconsole()
1718 list_add(&nt->list, &target_list); in init_netconsole()
1747 * from the boot/module option exist here). Skipping the list in init_netconsole()
1750 list_for_each_entry_safe(nt, tmp, &target_list, list) { in init_netconsole()
1751 list_del(&nt->list); in init_netconsole()
1773 * destroy them. Skipping the list lock is safe here, and in cleanup_netconsole()
1776 list_for_each_entry_safe(nt, tmp, &target_list, list) { in cleanup_netconsole()
1777 list_del(&nt->list); in cleanup_netconsole()
1784 * initialized after network device driver if built-in.