#include "smc_tracepoint.h"
 #include "smc_sysctl.h"
 #include "smc_loopback.h"
+#include "smc_inet.h"
 
 static DEFINE_MUTEX(smc_server_lgr_pending);   /* serialize link group
                                                 * creation on server
                pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
                goto out_lo;
        }
-
+       rc = smc_inet_init();
+       if (rc) {
+               pr_err("%s: smc_inet_init fails with %d\n", __func__, rc);
+               goto out_ulp;
+       }
        static_branch_enable(&tcp_have_smc);
        return 0;
-
+out_ulp:
+       tcp_unregister_ulp(&smc_ulp_ops);
 out_lo:
        smc_loopback_exit();
 out_ib:
 static void __exit smc_exit(void)
 {
        static_branch_disable(&tcp_have_smc);
+       smc_inet_exit();
        tcp_unregister_ulp(&smc_ulp_ops);
        sock_unregister(PF_SMC);
        smc_core_exit();
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(PF_SMC);
 MODULE_ALIAS_TCP_ULP("smc");
+/* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1);
+#if IS_ENABLED(CONFIG_IPV6)
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 256, 1);
+#endif /* CONFIG_IPV6 */
 MODULE_ALIAS_GENL_FAMILY(SMC_GENL_FAMILY_NAME);
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  Shared Memory Communications over RDMA (SMC-R) and RoCE
+ *
+ *  Definitions for the IPPROTO_SMC (socket related)
+ *
+ *  Copyright IBM Corp. 2016, 2018
+ *  Copyright (c) 2024, Alibaba Inc.
+ *
+ *  Author: D. Wythe <alibuda@linux.alibaba.com>
+ */
+
+#include <net/protocol.h>
+#include <net/sock.h>
+
+#include "smc_inet.h"
+#include "smc.h"
+
+static int smc_inet_init_sock(struct sock *sk);
+
+static struct proto smc_inet_prot = {
+       .name           = "INET_SMC",
+       .owner          = THIS_MODULE,
+       .init           = smc_inet_init_sock,
+       .hash           = smc_hash_sk,
+       .unhash         = smc_unhash_sk,
+       .release_cb     = smc_release_cb,
+       .obj_size       = sizeof(struct smc_sock),
+       .h.smc_hash     = &smc_v4_hashinfo,
+       .slab_flags     = SLAB_TYPESAFE_BY_RCU,
+};
+
+static const struct proto_ops smc_inet_stream_ops = {
+       .family         = PF_INET,
+       .owner          = THIS_MODULE,
+       .release        = smc_release,
+       .bind           = smc_bind,
+       .connect        = smc_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = smc_accept,
+       .getname        = smc_getname,
+       .poll           = smc_poll,
+       .ioctl          = smc_ioctl,
+       .listen         = smc_listen,
+       .shutdown       = smc_shutdown,
+       .setsockopt     = smc_setsockopt,
+       .getsockopt     = smc_getsockopt,
+       .sendmsg        = smc_sendmsg,
+       .recvmsg        = smc_recvmsg,
+       .mmap           = sock_no_mmap,
+       .splice_read    = smc_splice_read,
+};
+
+static struct inet_protosw smc_inet_protosw = {
+       .type           = SOCK_STREAM,
+       .protocol       = IPPROTO_SMC,
+       .prot           = &smc_inet_prot,
+       .ops            = &smc_inet_stream_ops,
+       .flags          = INET_PROTOSW_ICSK,
+};
+
+#if IS_ENABLED(CONFIG_IPV6)
+static struct proto smc_inet6_prot = {
+       .name           = "INET6_SMC",
+       .owner          = THIS_MODULE,
+       .init           = smc_inet_init_sock,
+       .hash           = smc_hash_sk,
+       .unhash         = smc_unhash_sk,
+       .release_cb     = smc_release_cb,
+       .obj_size       = sizeof(struct smc_sock),
+       .h.smc_hash     = &smc_v6_hashinfo,
+       .slab_flags     = SLAB_TYPESAFE_BY_RCU,
+};
+
+static const struct proto_ops smc_inet6_stream_ops = {
+       .family         = PF_INET6,
+       .owner          = THIS_MODULE,
+       .release        = smc_release,
+       .bind           = smc_bind,
+       .connect        = smc_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = smc_accept,
+       .getname        = smc_getname,
+       .poll           = smc_poll,
+       .ioctl          = smc_ioctl,
+       .listen         = smc_listen,
+       .shutdown       = smc_shutdown,
+       .setsockopt     = smc_setsockopt,
+       .getsockopt     = smc_getsockopt,
+       .sendmsg        = smc_sendmsg,
+       .recvmsg        = smc_recvmsg,
+       .mmap           = sock_no_mmap,
+       .splice_read    = smc_splice_read,
+};
+
+static struct inet_protosw smc_inet6_protosw = {
+       .type           = SOCK_STREAM,
+       .protocol       = IPPROTO_SMC,
+       .prot           = &smc_inet6_prot,
+       .ops            = &smc_inet6_stream_ops,
+       .flags          = INET_PROTOSW_ICSK,
+};
+#endif /* CONFIG_IPV6 */
+
+static int smc_inet_init_sock(struct sock *sk)
+{
+       struct net *net = sock_net(sk);
+
+       /* init common smc sock */
+       smc_sk_init(net, sk, IPPROTO_SMC);
+       /* create clcsock */
+       return smc_create_clcsk(net, sk, sk->sk_family);
+}
+
+int __init smc_inet_init(void)
+{
+       int rc;
+
+       rc = proto_register(&smc_inet_prot, 1);
+       if (rc) {
+               pr_err("%s: proto_register smc_inet_prot fails with %d\n",
+                      __func__, rc);
+               return rc;
+       }
+       /* no return value */
+       inet_register_protosw(&smc_inet_protosw);
+
+#if IS_ENABLED(CONFIG_IPV6)
+       rc = proto_register(&smc_inet6_prot, 1);
+       if (rc) {
+               pr_err("%s: proto_register smc_inet6_prot fails with %d\n",
+                      __func__, rc);
+               goto out_inet6_prot;
+       }
+       rc = inet6_register_protosw(&smc_inet6_protosw);
+       if (rc) {
+               pr_err("%s: inet6_register_protosw smc_inet6_protosw fails with %d\n",
+                      __func__, rc);
+               goto out_inet6_protosw;
+       }
+       return rc;
+out_inet6_protosw:
+       proto_unregister(&smc_inet6_prot);
+out_inet6_prot:
+       inet_unregister_protosw(&smc_inet_protosw);
+       proto_unregister(&smc_inet_prot);
+#endif /* CONFIG_IPV6 */
+       return rc;
+}
+
+void smc_inet_exit(void)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+       inet6_unregister_protosw(&smc_inet6_protosw);
+       proto_unregister(&smc_inet6_prot);
+#endif /* CONFIG_IPV6 */
+       inet_unregister_protosw(&smc_inet_protosw);
+       proto_unregister(&smc_inet_prot);
+}