diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index 25b052729d48..0099d9d6cc39 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -43,7 +43,7 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
 	switchgroup.o uxsock.o print.o alias.o log_pthread.o \
 	log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
 	lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \
-	io_err_stat.o
+	io_err_stat.o dm-generic.o generic.o
 
 all: $(LIBS)
 
diff --git a/libmultipath/dm-generic.c b/libmultipath/dm-generic.c
new file mode 100644
index 000000000000..42a26085d087
--- /dev/null
+++ b/libmultipath/dm-generic.c
@@ -0,0 +1,70 @@
+/*
+  Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+  USA.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include "generic.h"
+#include "dm-generic.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "config.h"
+#include "print.h"
+
+static const struct _vector*
+dm_mp_get_pgs(const struct gen_multipath *gmp)
+{
+	return vector_convert(NULL, gen_multipath_to_dm(gmp)->pg,
+			      struct pathgroup, dm_pathgroup_to_gen);
+}
+
+static void dm_mp_rel_pgs(const struct gen_multipath *gmp,
+			  const struct _vector* v)
+{
+	vector_free_const(v);
+}
+
+static const struct _vector*
+dm_pg_get_paths(const struct gen_pathgroup *gpg)
+{
+	return vector_convert(NULL, gen_pathgroup_to_dm(gpg)->paths,
+			      struct path, dm_path_to_gen);
+}
+
+static void dm_mp_rel_paths(const struct gen_pathgroup *gpg,
+			    const struct _vector* v)
+{
+	vector_free_const(v);
+}
+
+const struct gen_multipath_ops dm_gen_multipath_ops = {
+	.get_pathgroups = dm_mp_get_pgs,
+	.rel_pathgroups = dm_mp_rel_pgs,
+	.snprint = snprint_multipath_attr,
+	/* .style = snprint_multipath_style, TBD */
+};
+
+const struct gen_pathgroup_ops dm_gen_pathgroup_ops = {
+	.get_paths = dm_pg_get_paths,
+	.rel_paths = dm_mp_rel_paths,
+	.snprint = snprint_pathgroup_attr,
+};
+
+const struct gen_path_ops dm_gen_path_ops = {
+	.snprint = snprint_path_attr,
+};
diff --git a/libmultipath/dm-generic.h b/libmultipath/dm-generic.h
new file mode 100644
index 000000000000..5d5972406819
--- /dev/null
+++ b/libmultipath/dm-generic.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+  USA.
+ */
+#ifndef _DM_GENERIC_H
+#define _DM_GENERIC_H
+#include "generic.h"
+#include "list.h" /* for container_of */
+#include "structs.h"
+
+#define dm_multipath_to_gen(mpp) (&((mpp)->generic_mp))
+#define gen_multipath_to_dm(gm) \
+	container_of_const((gm), struct multipath, generic_mp)
+
+#define dm_pathgroup_to_gen(pg) (&(pg->generic_pg))
+#define gen_pathgroup_to_dm(gpg) \
+	container_of_const((gpg), struct pathgroup, generic_pg)
+
+#define dm_path_to_gen(pp) (&((pp)->generic_path))
+#define gen_path_to_dm(gp) \
+	container_of_const((gp), struct path, generic_path)
+
+extern const struct gen_multipath_ops dm_gen_multipath_ops;
+extern const struct gen_pathgroup_ops dm_gen_pathgroup_ops;
+extern const struct gen_path_ops dm_gen_path_ops;
+
+#endif /* _DM_GENERIC_H */
diff --git a/libmultipath/generic.c b/libmultipath/generic.c
new file mode 100644
index 000000000000..45012d0e1d95
--- /dev/null
+++ b/libmultipath/generic.c
@@ -0,0 +1,39 @@
+/*
+  Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+  USA.
+ */
+
+
+#include <string.h>
+#include "generic.h"
+#include "structs.h"
+
+int generic_style(const struct gen_multipath* gm,
+		  char *buf, int len, int verbosity)
+{
+	char alias_buf[WWID_SIZE];
+	char wwid_buf[WWID_SIZE];
+	int n = 0;
+
+	gm->ops->snprint(gm, alias_buf, sizeof(alias_buf), 'n');
+	gm->ops->snprint(gm, wwid_buf, sizeof(wwid_buf), 'w');
+
+	n += snprintf(buf, len, "%%n %s%%d %%s",
+		      strcmp(alias_buf, wwid_buf) ? "(%w) " : "");
+
+	return (n < len ? n : len - 1);
+}
diff --git a/libmultipath/generic.h b/libmultipath/generic.h
new file mode 100644
index 000000000000..7f7fe6661c36
--- /dev/null
+++ b/libmultipath/generic.h
@@ -0,0 +1,136 @@
+/*
+  Copyright (c) 2018 Martin Wilck, SUSE Linux GmbH
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version 2
+  of the License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+  USA.
+ */
+#ifndef _GENERIC_H
+#define _GENERIC_H
+#include "vector.h"
+
+struct gen_multipath;
+struct gen_pathgroup;
+struct gen_path;
+
+/**
+ * Methods implemented for gen_multipath "objects"
+ */
+struct gen_multipath_ops {
+	/**
+	 * method: get_pathgroups(gmp)
+	 * caller is responsible to returned data using rel_pathgroups()
+	 * caller is also responsible to lock the gmp (directly or indirectly)
+	 * while working with the return value.
+	 * @param gmp: generic multipath object to act on
+	 * @returns a vector of const struct gen_pathgroup*
+	 */
+	const struct _vector* (*get_pathgroups)(const struct gen_multipath*);
+	/**
+	 * method: rel_pathgroups(gmp, v)
+	 * free data allocated by get_pathgroups(), if any
+	 * @param gmp: generic multipath object to act on
+	 * @param v the value returned by get_pathgroups()
+	 */
+	void (*rel_pathgroups)(const struct gen_multipath*,
+			       const struct _vector*);
+	/**
+	 * method: snprint(gmp, buf, len, wildcard)
+	 * prints the property of the multipath map matching
+	 * the passed-in wildcard character into "buf",
+	 * 0-terminated, no more than "len" characters including trailing '\0'.
+	 *
+	 * @param gmp: generic multipath object to act on
+	 * @param buf: output buffer
+	 * @param buflen: buffer size
+	 * @param wildcard: the multipath wildcard (see print.c)
+	 * @returns the number of characters printed (without trailing '\0').
+	 */
+	int (*snprint)(const struct gen_multipath*,
+		       char *buf, int len, char wildcard);
+	/**
+	 * method: style(gmp, buf, len, verbosity)
+	 * returns the format string to be used for the multipath object,
+	 * defined with the wildcards as defined in print.c
+	 * generic_style() should work well in most cases.
+	 * @param gmp: generic multipath object to act on
+	 * @param buf: output buffer
+	 * @param buflen: buffer size
+	 * @param verbosity: verbosity level
+	 * @returns number of format chars printed
+	 */
+	int (*style)(const struct gen_multipath*,
+		     char *buf, int len, int verbosity);
+};
+
+/**
+ * Methods implemented for gen_pathgroup "objects"
+ */
+struct gen_pathgroup_ops {
+	/**
+	 * method: get_paths(gpg)
+	 * caller is responsible to returned data using rel_paths()
+	 * @param gpg: generic pathgroup object to act on
+	 * @returns a vector of const struct gen_path*
+	 */
+	const struct _vector* (*get_paths)(const struct gen_pathgroup*);
+	/**
+	 * method: rel_paths(gpg, v)
+	 * free data allocated by get_paths(), if any
+	 * @param gmp: generic pathgroup object to act on
+	 * @param v the value returned by get_paths()
+	 */
+	void (*rel_paths)(const struct gen_pathgroup*, const struct _vector*);
+	/**
+	 * Method snprint()
+	 * see gen_multipath_ops->snprint() above
+	 */
+	int (*snprint)(const struct gen_pathgroup*,
+		       char *buf, int len, char wildcard);
+};
+
+struct gen_path_ops {
+	/**
+	 * Method snprint()
+	 * see gen_multipath_ops->snprint() above
+	 */
+	int (*snprint)(const struct gen_path*,
+		       char *buf, int len, char wildcard);
+};
+
+struct gen_multipath {
+	const struct gen_multipath_ops *ops;
+};
+
+struct gen_pathgroup {
+	const struct gen_pathgroup_ops *ops;
+};
+
+struct gen_path {
+	const struct gen_path_ops *ops;
+};
+
+/**
+ * Helper functions for setting up the various generic_X_ops
+ */
+
+/**
+ * generic_style()
+ * A simple style() method (see above) that should fit most
+ * foreign libraries.
+ */
+int generic_style(const struct gen_multipath*,
+		  char *buf, int len, int verbosity);
+
+#endif /* _GENERIC_H */
diff --git a/libmultipath/list.h b/libmultipath/list.h
index c9110ac9de7e..ced021f5a633 100644
--- a/libmultipath/list.h
+++ b/libmultipath/list.h
@@ -18,6 +18,10 @@
  * @member:	the name of the member within the struct.
  *
  */
+#define container_of_const(ptr, type, member) ({		\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	(const type *)( (const char *)__mptr - offsetof(type,member) );})
+
 #define container_of(ptr, type, member) ({		\
 	typeof( ((type *)0)->member ) *__mptr = (ptr);	\
 	(type *)( (char *)__mptr - offsetof(type,member) );})
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 594ca567e22a..e9b8fdd6e581 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -756,6 +756,17 @@ mpd_lookup(char wildcard)
 	return NULL;
 }
 
+int snprint_multipath_attr(const struct gen_multipath* gm,
+			   char *buf, int len, char wildcard)
+{
+	const struct multipath *mpp = gen_multipath_to_dm(gm);
+	struct multipath_data *mpd = mpd_lookup(wildcard);
+
+	if (mpd == NULL)
+		return 0;
+	return mpd->snprint(buf, len, mpp);
+}
+
 static struct path_data *
 pd_lookup(char wildcard)
 {
@@ -768,6 +779,17 @@ pd_lookup(char wildcard)
 	return NULL;
 }
 
+int snprint_path_attr(const struct gen_path* gp,
+		      char *buf, int len, char wildcard)
+{
+	const struct path *pp = gen_path_to_dm(gp);
+	struct path_data *pd = pd_lookup(wildcard);
+
+	if (pd == NULL)
+		return 0;
+	return pd->snprint(buf, len, pp);
+}
+
 static struct pathgroup_data *
 pgd_lookup(char wildcard)
 {
@@ -780,6 +802,17 @@ pgd_lookup(char wildcard)
 	return NULL;
 }
 
+int snprint_pathgroup_attr(const struct gen_pathgroup* gpg,
+			   char *buf, int len, char wildcard)
+{
+	const struct pathgroup *pg = gen_pathgroup_to_dm(gpg);
+	struct pathgroup_data *pdg = pgd_lookup(wildcard);
+
+	if (pdg == NULL)
+		return 0;
+	return pdg->snprint(buf, len, pg);
+}
+
 int
 snprint_multipath_header (char * line, int len, const char * format)
 {
diff --git a/libmultipath/print.h b/libmultipath/print.h
index 02c5b072cc2b..214777c1e4f8 100644
--- a/libmultipath/print.h
+++ b/libmultipath/print.h
@@ -1,3 +1,7 @@
+#ifndef _PRINT_H
+#define _PRINT_H
+#include "dm-generic.h"
+
 #define PRINT_PATH_LONG      "%w %i %d %D %p %t %T %s %o"
 #define PRINT_PATH_INDENT    "%i %d %D %t %T %o"
 #define PRINT_PATH_CHECKER   "%i %d %D %p %t %T %o %C"
@@ -122,3 +126,11 @@ int snprint_tgt_wwpn (char *, size_t, const struct path *);
 void print_multipath_topology (struct multipath * mpp, int verbosity);
 void print_all_paths (vector pathvec, int banner);
 void print_all_paths_custo (vector pathvec, int banner, char *fmt);
+
+int snprint_path_attr(const struct gen_path* gp,
+		      char *buf, int len, char wildcard);
+int snprint_pathgroup_attr(const struct gen_pathgroup* gpg,
+			   char *buf, int len, char wildcard);
+int snprint_multipath_attr(const struct gen_multipath* gm,
+			   char *buf, int len, char wildcard);
+#endif /* _PRINT_H */
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 4db08451824d..991095cb2bc1 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -18,6 +18,7 @@
 #include "blacklist.h"
 #include "prio.h"
 #include "prioritizers/alua_spc3.h"
+#include "dm-generic.h"
 
 struct adapter_group *
 alloc_adaptergroup(void)
@@ -100,6 +101,7 @@ alloc_path (void)
 		pp->tpgs = TPGS_UNDEF;
 		pp->priority = PRIO_UNDEF;
 		checker_clear(&pp->checker);
+		dm_path_to_gen(pp)->ops = &dm_gen_path_ops;
 	}
 	return pp;
 }
@@ -160,6 +162,7 @@ alloc_pathgroup (void)
 		pgp = NULL;
 	}
 
+	dm_pathgroup_to_gen(pgp)->ops = &dm_gen_pathgroup_ops;
 	return pgp;
 }
 
@@ -200,6 +203,7 @@ alloc_multipath (void)
 		mpp->mpcontext = NULL;
 		mpp->no_path_retry = NO_PATH_RETRY_UNDEF;
 		mpp->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
+		dm_multipath_to_gen(mpp)->ops = &dm_gen_multipath_ops;
 	}
 	return mpp;
 }
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index bccc845a1222..88a4b7862393 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -6,6 +6,7 @@
 
 #include "prio.h"
 #include "byteorder.h"
+#include "generic.h"
 
 #define WWID_SIZE		128
 #define SERIAL_SIZE		65
@@ -256,6 +257,7 @@ struct path {
 	int io_err_pathfail_starttime;
 	/* configlet pointers */
 	struct hwentry * hwe;
+	struct gen_path generic_path;
 };
 
 typedef int (pgpolicyfn) (struct multipath *);
@@ -332,6 +334,7 @@ struct multipath {
 	int prkey_source;
 	struct be64 reservation_key;
 	unsigned char prflag;
+	struct gen_multipath generic_mp;
 };
 
 struct pathgroup {
@@ -341,6 +344,7 @@ struct pathgroup {
 	int enabled_paths;
 	vector paths;
 	struct multipath *mpp;
+	struct gen_pathgroup generic_pg;
 };
 
 struct adapter_group {
