Re: failed to build nikal error on RHEL7 (3.10.0-862.3.2.el7.x86_64)

Ok I may have a way to fix these compilation errors without simply adding comments to the code.  I will preface by saying I am a scientist/engineer working on nuclear fusion, not a software developer.  I am posting this to throw my rock on this pile and contribute my findings, not as a permanent solution.  Clearly NI needs some serious overhaul with regards to Linux compatibility.


Because the implicit declaration error seemed to be a function call error, I searched through the genetlink.h header file, which was located here for me:  /usr/src/kernels/3.10.0-514.10.2.el7.x86_64/include/net/genetlink.h.  I could not find a function / method: genl_register_family_with_ops() in this header file, or in any of the header file that genetlink.h includes.  After a trip through the internet wormhole, I found this thread, which indicated that even though I was running the RHEL kernel 3.10, genl_register_family_with_ops() had possibly been deprecated early.  The deprecation is supposed to happen after 4.10, according to Linux Foundation Netlink Howto.


All that being said, this is what I did, and I am communicating with ENET devices using GPIBEXPLORER.

  1. Include: NULL in do_munmap(), as indicated in other threads on this site
  2. Add: GENL_ID_GENERATE 0 as another poster in this thread indicated
  3. Switch order of (including code inside brackets):
    1. static struct genl_ops{}
    2. static struct genl_family{}
  4. Include two references to genl_ops structure as elements in the genl_family structure:
    1.   .ops = nikal_netlink_ops,
    2.   .n_ops = 1
  5. Change the #ifdef nNIKAL1400_kHasFamilyGenlOpsGroups conditional (and else statement) to:
    1. if ((status = genl_register_family(&nikal_netlink_family))) return status;

I have included the entire snippet of this code below.  I am sure I missed something here, so if anyone sees anything really bad please let me know.  I think there is probably a better way to handle the conditional.  In my code below it serves no real purpose.


EDIT (20180716): Using NI-KAL 17.5 solves this issue.  All the errors / modifications mentioned above are included in this version of nikal.c.  See other accepted solution below.  I will keep both marked as solution because here I give a description of the problem with the source.


#define NLNIKAL_CMD_SEND     1

// Begin Mod

/* Modified 20180618 by TL
 * genl_register_family_with_ops() is (apparently) no longer existent
 * for this kernel version in RHEL.  Instead, we reference netlink_ops from
 * netlink_family using two elements, .ops and .n_ops, and then replace
 * the genl_register_family_with_ops() call with genl_register_family().
 * Obviously, this is hacky, but until NI codes distro checking into
 * their modules this will have to do.  I am not sure about all the
 * effects of this, but I am sure there are some inadvertent byproducts
 * of doing this that I am unaware of.  So far, I have communicated with
 * E100s over multiple subnets using driver compiled with this code.
 * Linux Foundation Netlink Webpage:
 * NI Discussion forum thread I made for this topic:

// Added 20180618 by TL
#define GENL_ID_GENERATE 0  // define value to genl_id_generate = 0

static int nlnikal_msg(struct sk_buff *skb, struct genl_info *info) { return 0; }

// Modified 20180618 by TL
// The order of genl_ops and genl_family used to be reversed.
static struct genl_ops nikal_netlink_ops[] =
      .cmd = NLNIKAL_CMD_SEND,
      .doit = nlnikal_msg

static struct genl_family nikal_netlink_family =
   .name = "nlnikal",
   .version = 1,
   .maxattr = 1,
   // Added 20180617 by TL
   // For newer kernel versions, we must reference netlink_ops
   .ops = nikal_netlink_ops,
   .n_ops = 1

static int __init nNIKAL100_initDriver(void)
   int status = 0;
   nNIKAL120_sStackSize = nNIKAL120_mRoundUp(((nNIKAL100_tUPtr)(&status) -
         (nNIKAL100_tUPtr)(current_thread_info())), PAGE_SIZE) -
         sizeof(struct thread_info);
   KAL_DPRINT("Kernel stack size: %lu\n", nNIKAL120_sStackSize);
   sema_init(&(nNIKAL100_sMMapSema), 1);
   sema_init(&(nNIKAL100_sPageLockOperationSema), 1);
   sema_init(&(nNIKAL100_sMallocContiguousMapLock), 1);

#ifdef nNIKAL1400_kHasFamilyGenlOpsGroups
    //Modified 20180618 by TL
    //Original Line of code from NI:
    // if ((status = genl_register_family_with_ops(&nikal_netlink_family, nikal_netlink_ops))) return status;
    // Tom's line:   
    if ((status = genl_register_family(&nikal_netlink_family))) return status;
    //Original Line from NI:
    // if ((status = genl_register_family_with_ops(&nikal_netlink_family, nikal_netlink_ops, 1))) return status;

    //Tom's Line:
    if ((status = genl_register_family(&nikal_netlink_family))) return status;

   nNIKAL200_sProcRootDir = proc_mkdir("driver/ni", NULL);

   if (!nNIKAL200_sProcRootDir)
      return -ENOMEM;

   return status;

// End Mod

static void __exit nNIKAL100_cleanupDriver(void)




0 Kudos