Some time ago I proposed a patch to enable enabling/disabling individual PEF policy entries. Support for this is needed for one of our utilities. A new rework of the whole PEF framework was requested. I'm attaching a patch that (partially) implements this new scheme, please review.
http://sourceforge.net/p/ipmitool/bugs/312/ diff --git a/include/ipmitool/ipmi_mc.h b/include/ipmitool/ipmi_mc.h index a840f78..fbd2c97 100644 --- a/include/ipmitool/ipmi_mc.h +++ b/include/ipmitool/ipmi_mc.h @@ -165,6 +165,8 @@ struct ipm_get_watchdog_rsp { #define IPMI_SYSINFO_OS_NAME 0x04 #define IPMI_SYSINFO_DELL_OS_VERSION 0xe4 #define IPMI_SYSINFO_DELL_URL 0xde +#define IPMI_SYSINFO_DELL_IPV6_COUNT 0xe6 +#define IPMI_SYSINFO_DELL_IPV6_DESTADDR 0xf0 int ipmi_mc_getsysinfo(struct ipmi_intf * intf, int param, int block, int set, int len, void *buffer); diff --git a/lib/ipmi_pef.c b/lib/ipmi_pef.c index 1beebf0..fd52663 100644 --- a/lib/ipmi_pef.c +++ b/lib/ipmi_pef.c @@ -38,6 +38,7 @@ #include <ipmitool/helper.h> #include <ipmitool/log.h> #include <ipmitool/ipmi.h> +#include <ipmitool/ipmi_mc.h> #include <ipmitool/ipmi_intf.h> #include <ipmitool/ipmi_pef.h> @@ -206,7 +207,7 @@ ipmi_pef_msg_exchange(struct ipmi_intf * intf, struct ipmi_rq * req, char * txt) static uint8_t ipmi_pef_get_policy_table(struct ipmi_intf * intf, - struct pef_cfgparm_policy_table_entry ** table) + struct pef_cfgparm_policy_table_entry ** table) { /* // get the PEF policy table: allocate space, fillin, and return its size // NB: the caller must free the returned area (when returned size> 0) @@ -257,6 +258,53 @@ ipmi_pef_get_policy_table(struct ipmi_intf * intf, } static void +ipmi_pef_print_oem_lan_dest(struct ipmi_intf *intf, uint8_t ch, uint8_t dest) +{ + int rc, i; + uint8_t data[32]; + char address[128]; + int len, set, rlen; + + if (ipmi_get_oem(intf) != IPMI_OEM_DELL) { + return; + } + /* Get # of IPV6 trap destinations */ + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_COUNT, 0x00, 0x00, 4, data); + if (rc != 0 || dest> data[0]) { + return; + } + ipmi_pef_print_str("Alert destination type", "xxx"); + ipmi_pef_print_str("PET Community", "xxx"); + ipmi_pef_print_dec("ACK timeout/retry (secs)", 0); + ipmi_pef_print_dec("Retries", 0); + + /* Get IPv6 destination string (may be in multiple sets) */ + memset(address, 0, sizeof(address)); + memset(data, 0, sizeof(data)); + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_DESTADDR, 0x00, dest, 19, data); + if (rc != 0) { + return; + } + /* Total length of IPv6 string */ + len = data[4]; + if ((rlen = len)> (IPMI_SYSINFO_SET0_SIZE-3)) { + /* First set has 11 bytes */ + rlen = IPMI_SYSINFO_SET0_SIZE - 3; + } + memcpy(address, data+8, rlen); + for (set = 1; len> 11; set++) { + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_DESTADDR, set, dest, 19, data); + if ((rlen = len-11)>= IPMI_SYSINFO_SETN_SIZE - 2) { + /* Remaining sets have 14 bytes */ + rlen = IPMI_SYSINFO_SETN_SIZE - 2; + } + memcpy(address+set*11, data+3, rlen); + len -= rlen+3; + } + ipmi_pef_print_str("IPv6 Address", address); +} + +static void ipmi_pef_print_lan_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) { /* // print LAN alert destination info @@ -284,6 +332,10 @@ ipmi_pef_print_lan_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) return; } tbl_size = (rsp->data[1] & PEF_LAN_DEST_TABLE_SIZE_MASK); + if (dest> tbl_size) { + ipmi_pef_print_oem_lan_dest(intf, ch, dest - tbl_size); + return; + } //if (tbl_size == 0 || dest == 0) /* LAN alerting not supported */ // return; @@ -579,7 +631,7 @@ ipmi_pef_print_event_info(struct pef_cfgparm_filter_table_entry * pef, char * bu static void ipmi_pef_print_entry(struct ipmi_rs * rsp, uint8_t id, - struct pef_cfgparm_filter_table_entry * pef) + struct pef_cfgparm_filter_table_entry * pef) { /* // print a PEF table entry */ @@ -686,50 +738,49 @@ ipmi_pef_list_policies(struct ipmi_intf * intf) req.msg.data = &ch; req.msg.data_len = sizeof(ch); for (ptmp=ptbl, i=1; i<=tbl_size; i++, ptmp++) { - if ((ptmp->entry.policy & PEF_POLICY_ENABLED) == PEF_POLICY_ENABLED) { - if (i> 1) - printf("\n"); - first_field = 1; - ipmi_pef_print_dec("Alert policy table entry", - (ptmp->data1 & PEF_POLICY_TABLE_ID_MASK)); - ipmi_pef_print_dec("Policy set", - (ptmp->entry.policy & PEF_POLICY_ID_MASK)>> PEF_POLICY_ID_SHIFT); - ipmi_pef_print_str("Policy entry rule", - ipmi_pef_bit_desc(&pef_b2s_policies, (ptmp->entry.policy & PEF_POLICY_FLAGS_MASK))); - - if (ptmp->entry.alert_string_key & PEF_POLICY_EVENT_SPECIFIC) { - ipmi_pef_print_str("Event-specific", "true"); -// continue; - } - wrk = ptmp->entry.chan_dest; - - /* channel/description */ - ch = (wrk & PEF_POLICY_CHANNEL_MASK)>> PEF_POLICY_CHANNEL_SHIFT; - rsp = ipmi_pef_msg_exchange(intf, &req, "Channel info"); - if (!rsp || rsp->data[0] != ch) { - lprintf(LOG_ERR, " **Error retrieving %s", - "Channel info"); - continue; - } - medium = rsp->data[1]; - ipmi_pef_print_dec("Channel number", ch); - ipmi_pef_print_str("Channel medium", - ipmi_pef_bit_desc(&pef_b2s_ch_medium, medium)); - - /* destination/description */ - wrk &= PEF_POLICY_DESTINATION_MASK; - switch (medium) { - case PEF_CH_MEDIUM_TYPE_LAN: - ipmi_pef_print_lan_dest(intf, ch, wrk); - break; - case PEF_CH_MEDIUM_TYPE_SERIAL: - ipmi_pef_print_serial_dest(intf, ch, wrk); - break; - default: - ipmi_pef_print_dest(intf, ch, wrk); - break; - } + first_field = 1; + ipmi_pef_print_dec("Alert policy table entry", + (ptmp->data1 & PEF_POLICY_TABLE_ID_MASK)); + ipmi_pef_print_dec("Policy set", + (ptmp->entry.policy & PEF_POLICY_ID_MASK)>> PEF_POLICY_ID_SHIFT); + ipmi_pef_print_str("State", + ptmp->entry.policy & PEF_POLICY_ENABLED ? "enabled" : "disabled"); + ipmi_pef_print_str("Policy entry rule", + ipmi_pef_bit_desc(&pef_b2s_policies, (ptmp->entry.policy & PEF_POLICY_FLAGS_MASK))); + + if (ptmp->entry.alert_string_key & PEF_POLICY_EVENT_SPECIFIC) { + ipmi_pef_print_str("Event-specific", "true"); + // continue; + } + wrk = ptmp->entry.chan_dest; + + /* channel/description */ + ch = (wrk & PEF_POLICY_CHANNEL_MASK)>> PEF_POLICY_CHANNEL_SHIFT; + rsp = ipmi_pef_msg_exchange(intf, &req, "Channel info"); + if (!rsp || rsp->data[0] != ch) { + lprintf(LOG_ERR, " **Error retrieving %s", + "Channel info"); + continue; + } + medium = rsp->data[1]; + ipmi_pef_print_dec("Channel number", ch); + ipmi_pef_print_str("Channel medium", + ipmi_pef_bit_desc(&pef_b2s_ch_medium, medium)); + + /* destination/description */ + wrk &= PEF_POLICY_DESTINATION_MASK; + switch (medium) { + case PEF_CH_MEDIUM_TYPE_LAN: + ipmi_pef_print_lan_dest(intf, ch, wrk); + break; + case PEF_CH_MEDIUM_TYPE_SERIAL: + ipmi_pef_print_serial_dest(intf, ch, wrk); + break; + default: + ipmi_pef_print_dest(intf, ch, wrk); + break; } + printf("\n"); } free(ptbl); ptbl = NULL; @@ -858,33 +909,258 @@ ipmi_pef_get_info(struct ipmi_intf * intf) ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, actions); } +int +ipmi_pef_timer(struct ipmi_intf *intf, int argc, char **argv) +{ + lprintf(LOG_ERR, "Not implemented"); + return (-1); +} + +void +ipmi_pef_policy_help(void) +{ + lprintf(LOG_NOTICE, + "usage: pef policy <command> [options"); + lprintf(LOG_NOTICE, + " list List enabled PEF policies"); +} + +void +ipmi_pef2_policy_help(void) +{ + lprintf(LOG_NOTICE, "usage: pef policy list"); + lprintf(LOG_NOTICE, " pef policy enable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef policy disable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef policy create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, " pef policy delete <id = 1..n>"); +} + +#define IPMI_CMD_SET_PEF_CONFIG_PARMS 0x12 +struct pef_cfgparm_set_policy_table_entry +{ + uint8_t id; + uint8_t sel; + struct pef_policy_entry entry; +} ATTRIBUTE_PACKING; + + +static int +ipmi_pef_set_policy_table_entry(struct ipmi_intf * intf, int set, struct pef_cfgparm_policy_table_entry *entry) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct pef_cfgparm_set_policy_table_entry psel; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_SET_PEF_CONFIG_PARMS; + req.msg.data = &psel; + req.msg.data_len = sizeof(psel); + + memset(&psel, 0, sizeof(psel)); + psel.id = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY; + psel.sel = set & 0x3F; + memcpy(&psel.entry, &entry->entry, sizeof(entry->entry)); + + rsp = ipmi_pef_msg_exchange(intf, &req, "Set Alert policy table entry"); + if (!rsp) { + lprintf(LOG_ERR, " **Error setting Alert policy table entry"); + return -1; + } + return 0; +} + +/* Enable/Disable specific PEF policy */ +static int +ipmi_pef2_policy_enable(struct ipmi_intf *intf, int enable, int argc, char **argv) +{ + struct pef_cfgparm_policy_table_entry * ptbl = NULL; + int tbl_size, id; + + if (argc < 1) { + ipmi_pef2_policy_help(); + return (-1); + } + tbl_size = ipmi_pef_get_policy_table(intf, &ptbl); + if (!tbl_size) { + if (ptbl != NULL) { + free(ptbl); + } + return (-1); + } + + /* Get policy ID number */ + id = strtol(argv[0], NULL, 0); + if (id>= 1 && id <= tbl_size) { + /* Check if already enabled or disabled */ + if ((enable && !(ptbl[id-1].entry.policy & PEF_POLICY_ENABLED)) || + (!enable && (ptbl[id-1].entry.policy & PEF_POLICY_ENABLED))) { + ptbl[id-1].entry.policy ^= PEF_POLICY_ENABLED; + return ipmi_pef_set_policy_table_entry(intf, id, &ptbl[id-1]); + } + else { + lprintf(LOG_ERR, "Policy %d already %s", id, enable ? "enabled" : "disabled"); + } + } else { + lprintf(LOG_ERR, "Invalid policy index, valid range = (1..%d)", tbl_size); + return (-1); + } + lprintf(LOG_INFO, "done\n"); + return (0); +} + +int +ipmi_pef2_policy(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_policy_help(); + rc = (-1); + } else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_policy_help(); + } + else if (!strncmp(argv[0], "list\0", 5)) { + ipmi_pef_list_policies(intf); + } + else if (!strncmp(argv[0], "enable\0", 7)) { + rc = ipmi_pef2_policy_enable(intf, 1, --argc, ++argv); + } + else if (!strncmp(argv[0], "disable\0", 8)) { + rc = ipmi_pef2_policy_enable(intf, 0, --argc, ++argv); + } + else if (!strncmp(argv[0], "create\0", 7)) { + } + else if (!strncmp(argv[0], "delete\0", 7)) { + } + else { + ipmi_pef2_policy_help(); + } + return rc; +} + +/* Enable/Disable specific PEF filter */ +static int +ipmi_pef2_filter_enable(struct ipmi_intf *intf, int enable, int argc, char **argv) +{ +} + +void +ipmi_pef2_filter_help(void) +{ + lprintf(LOG_NOTICE, "usage: pef filter list"); + lprintf(LOG_NOTICE, " pef filter enable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef filter disable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef filter create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, " pef filter delete <id = 1..n>"); +} + +int +ipmi_pef2_filter(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_filter_help(); + rc = (-1); + } + else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_filter_help(); + } + else if (!strncmp(argv[0], "list\0", 5)) { + ipmi_pef_list_entries(intf); + } + else if (!strncmp(argv[0], "enable\0", 7)) { + } + else if (!strncmp(argv[0], "disable\0", 8)) { + } + else if (!strncmp(argv[0], "create\0", 7)) { + } + else if (!strncmp(argv[0], "delete\0", 7)) { + } + else { + //ipmi_pef2_filterhelp(); + } + return rc; +} + +void +ipmi_pef2_help(void) +{ + lprintf(LOG_NOTICE, "usage: pef help"); + lprintf(LOG_NOTICE, " pef timer get"); + lprintf(LOG_NOTICE, " pef timer set"); + lprintf(LOG_NOTICE, " pef policy list"); + lprintf(LOG_NOTICE, " pef policy enable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef policy disable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef policy create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, " pef policy delete <id = 1..n>"); + lprintf(LOG_NOTICE, " pef filter list"); + lprintf(LOG_NOTICE, " pef filter enable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef filter disable <id = 1..n>"); + lprintf(LOG_NOTICE, " pef filter create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, " pef filter delete <id = 1..n>"); + lprintf(LOG_NOTICE, " pef pet ack <params>"); +} + +/* + pef help + pef timer get + pef timer set <xxx> + pef policy list + pef policy enable <id> + pef policy disable <id> + pef policy create <id> <params> + pef policy delete <id> + pef filter list + pef filter enable <id> + pef filter disable <id> + pef filter create <id> <params> + pef filter delete <id> + pef pet ack <params> +*/ int ipmi_pef_main(struct ipmi_intf * intf, int argc, char ** argv) { /* // PEF subcommand handling */ - int help = 0; - int rc = 0; - - if (!argc || !strncmp(argv[0], "info", 4)) - ipmi_pef_get_info(intf); - else if (!strncmp(argv[0], "help", 4)) - help = 1; - else if (!strncmp(argv[0], "status", 6)) - ipmi_pef_get_status(intf); - else if (!strncmp(argv[0], "policy", 6)) - ipmi_pef_list_policies(intf); - else if (!strncmp(argv[0], "list", 4)) - ipmi_pef_list_entries(intf); + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_help(); + rc = (-1); + } + else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_help(); + rc = 0; + } + else if (!strncmp(argv[0], "info\0", 5) + || !strncmp(argv[0], "capabilities\0", 13)) { + //rc = ipmi_pef2_get_capabilities(intf); + } + else if (!strncmp(argv[0], "event\0", 6)) { + //rc = ipmi_pef2_event(intf, (argc - 1), ++argv); + } + else if (!strncmp(argv[0], "filter\0", 7)) { + rc = ipmi_pef2_filter(intf, (argc - 1), ++argv); + } + else if (!strncmp(argv[0], "policy\0", 7)) { + rc = ipmi_pef2_policy(intf, (argc - 1), ++argv); + } + else if (!strncmp(argv[0], "pet\0", 4)) { + //rc = ipmi_pef2_pet(intf, (argc - 1), ++argv); + } + else if (!strncmp(argv[0], "status\0", 7)) { + //rc = ipmi_pef2_get_status(intf, (argc - 1), ++argv); + } + else if (!strncmp(argv[0], "timer\0", 6)) { + //rc = ipmi_pef2_timer(intf, (argc - 1), ++argv); + } else { - help = 1; - rc = -1; lprintf(LOG_ERR, "Invalid PEF command: '%s'\n", argv[0]); + rc = (-1); } - - if (help) - lprintf(LOG_NOTICE, "PEF commands: info status policy list"); - else if (!verbose) - printf("\n"); - return rc; } ------------------------------------------------------------------------------ _______________________________________________ Ipmitool-devel mailing list Ipmitool-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ipmitool-devel